Spaces:
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, a11oy_ayllu.py, a11oy_brain_graph.py, a11oy_code_engine.py, a11oy_code_orchestrator.py, a11oy_frontier_page.py, a11oy_frontier_patch.py, a11oy_hf_assets.py, a11oy_nemo_core.py, a11oy_operator_organ.py, a11oy_org_rag.py, ayllu/__init__.py, ayllu/backend.py, ayllu/loop.py, ayllu/lounge.py, ayllu/model_binding.py, ayllu/selftest.py, model_release/receipt-agent/receipt_runtime.py, numerics/isolation_probe.py, research/__init__.py, serve.py, szl3d_holographic.py, szl_alloy_models.py, szl_anatomy_3d.py, szl_anatomy_brainloop.py, szl_boot_preflight.py, szl_brain_api.py, szl_brain_reranker.py, szl_brain_training_admission.py, szl_braincorpus.py, szl_brainhealth.py, szl_claim_rupture_gate.py, szl_formal_conjecture_lab.py, szl_governed_infer.py, szl_gpu_quant.py, szl_llm_registry.py, szl_m1_corpus_manifest.py, szl_m1_model_gate.py, szl_nemo_agents.py, szl_numerics_adapter.py, szl_numerics_dataset.py, szl_numerics_experiment.py, szl_provider_http.py, szl_quant_qbio_holo.py, szl_quantum_bio.py, szl_quantum_utility.py, szl_release_identity.py, szl_waqay.py, szl_yupaq_compute.py, szl_yupay.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 +59 -2
- a11oy_ayllu.py +223 -39
- a11oy_brain_graph.py +5 -4
- a11oy_code_engine.py +72 -3
- a11oy_code_orchestrator.py +472 -37
- a11oy_frontier_page.py +419 -38
- a11oy_frontier_patch.py +21 -7
- a11oy_hf_assets.py +2 -2
- a11oy_nemo_core.py +236 -96
- a11oy_operator_organ.py +4 -4
- a11oy_org_rag.py +672 -74
- ayllu/__init__.py +5 -4
- ayllu/backend.py +145 -6
- ayllu/loop.py +23 -3
- ayllu/lounge.py +16 -10
- ayllu/model_binding.py +402 -0
- ayllu/selftest.py +4 -3
- model_release/receipt-agent/receipt_runtime.py +511 -0
- numerics/isolation_probe.py +38 -0
- research/__init__.py +0 -1
- serve.py +342 -24
- szl3d_holographic.py +2 -0
- szl_alloy_models.py +64 -8
- szl_anatomy_3d.py +10 -0
- szl_anatomy_brainloop.py +24 -0
- szl_boot_preflight.py +6 -0
- szl_brain_api.py +35 -3
- szl_brain_reranker.py +978 -0
- szl_brain_training_admission.py +1221 -0
- szl_braincorpus.py +644 -0
- szl_brainhealth.py +370 -5
- szl_claim_rupture_gate.py +0 -1
- szl_formal_conjecture_lab.py +727 -0
- szl_governed_infer.py +101 -5
- szl_gpu_quant.py +30 -17
- szl_llm_registry.py +455 -96
- szl_m1_corpus_manifest.py +363 -0
- szl_m1_model_gate.py +833 -0
- szl_nemo_agents.py +22 -17
- szl_numerics_adapter.py +532 -0
- szl_numerics_dataset.py +1000 -0
- szl_numerics_experiment.py +482 -0
- szl_provider_http.py +463 -0
- szl_quant_qbio_holo.py +16 -1
- szl_quantum_bio.py +27 -5
- szl_quantum_utility.py +724 -0
- szl_release_identity.py +114 -0
- szl_waqay.py +6 -6
- szl_yupaq_compute.py +875 -0
- szl_yupay.py +6 -6
|
@@ -163,12 +163,59 @@ 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 |
# Waqay Security Loop wave 15: pure read-only proposal contract. The module
|
| 167 |
# exposes zero external effectors; serve.py registers only its manifest GET.
|
| 168 |
COPY szl_waqay_security_loop.py ./
|
| 169 |
# Claim-integrity Rupture Gate wave 15: contract-only, external signals only,
|
| 170 |
# unsigned deterministic receipts, zero effectors.
|
| 171 |
COPY szl_claim_rupture_gate.py ./
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
# Primary official project registry (51 records across 10 fields). Runtime
|
| 173 |
# serves the deterministic, unranked registry; optional live metadata remains a
|
| 174 |
# bounded adapter and is not executed on anonymous public requests.
|
|
@@ -659,7 +706,7 @@ COPY benchmarks/pinn/run_bench.py ./benchmarks/pinn/run_bench.py
|
|
| 659 |
# hf-sync mirrored) — same baked-only pattern as web/sda.html + web/immune.html;
|
| 660 |
# declared in copy-sync-lockstep.json image_only_assets + hf-module-drift-allow.json
|
| 661 |
# accepted_divergences.
|
| 662 |
-
COPY web/formulas.html web/v4_fleet_panel.html web/operator.html web/fleet-c2.html web/living-anatomy.html web/nemo.html web/restraint.html web/restraint-bench.html web/holo.html web/constitution.html web/quant.html web/estate-hologram.html web/hologram.html web/determinacy.html web/verify-receipt.html web/sda.html web/dns.html ./web/
|
| 663 |
COPY web/signature-is-not-proof.html ./web/signature-is-not-proof.html
|
| 664 |
COPY web/defense-readiness.html ./web/defense-readiness.html
|
| 665 |
# ADDITIVE (Lane A AGENTIC CORE, Dev A, 2026-06-14; QA9 restore 2026-06): the
|
|
@@ -1563,6 +1610,9 @@ COPY szl_brainconsensus.py ./szl_brainconsensus.py
|
|
| 1563 |
# brainqueryaudit.js ships via the existing whole-tree `COPY static/3d/ ./static/3d/`
|
| 1564 |
# above. RECORDS/OBSERVES only — adds NOTHING to the locked-8; Λ = Conjecture 1; trust 0.97.
|
| 1565 |
COPY szl_brainqueryaudit.py ./szl_brainqueryaudit.py
|
|
|
|
|
|
|
|
|
|
| 1566 |
# BRAIN LINEAGE (feat/frontier-brainlineage) — NODE-ORIGIN lineage over the SAME
|
| 1567 |
# honest brain graph: for a node id or a query's top nodes it reports HOW each node
|
| 1568 |
# ENTERED the graph, read VERBATIM from the node's OWN real origin fields
|
|
@@ -1656,7 +1706,14 @@ COPY a11oy_quant_signals_nav.py ./a11oy_quant_signals_nav.py
|
|
| 1656 |
ARG SZL_GIT_SHA=unknown
|
| 1657 |
ARG SZL_BUILD_TIME=unknown
|
| 1658 |
ENV SZL_GIT_SHA=${SZL_GIT_SHA} \
|
| 1659 |
-
SZL_BUILD_TIME=${SZL_BUILD_TIME}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1660 |
CMD ["python", "serve.py"]
|
| 1661 |
|
| 1662 |
|
|
|
|
| 163 |
# registers live. (dockerfile-copy-guard verifies these sources exist on main.)
|
| 164 |
COPY a11oy_ayllu.py ./
|
| 165 |
COPY ayllu/ ./ayllu/
|
| 166 |
+
# Canonical model-family/control-plane evidence ships with the runtime image so
|
| 167 |
+
# deployed status surfaces can be audited against the same release contracts.
|
| 168 |
+
COPY model_release/szl-forge-family.json model_release/szl-compute-plane.json model_release/szl-ayllu-binding.json model_release/szl-khipu-second-brain.json ./model_release/
|
| 169 |
+
COPY model_release/receipt-agent/ ./model_release/receipt-agent/
|
| 170 |
+
# Brain-derived rows remain quarantined until this deterministic, fail-closed
|
| 171 |
+
# admission engine validates immutable provenance, rights, contamination, and
|
| 172 |
+
# split obligations. Shipping the CLI does not start training or admit rows.
|
| 173 |
+
COPY szl_brain_training_admission.py ./
|
| 174 |
# Waqay Security Loop wave 15: pure read-only proposal contract. The module
|
| 175 |
# exposes zero external effectors; serve.py registers only its manifest GET.
|
| 176 |
COPY szl_waqay_security_loop.py ./
|
| 177 |
# Claim-integrity Rupture Gate wave 15: contract-only, external signals only,
|
| 178 |
# unsigned deterministic receipts, zero effectors.
|
| 179 |
COPY szl_claim_rupture_gate.py ./
|
| 180 |
+
# Quantum Utility Gate wave 16: pure-stdlib proposal analysis only. No provider
|
| 181 |
+
# SDK, QPU call, credential path, external effector, or finance-engine coupling.
|
| 182 |
+
COPY szl_quantum_utility.py ./
|
| 183 |
+
# Wave 18 numerical-engine frontier. These are only the Apache-2.0 host contract
|
| 184 |
+
# and fixed data-only Octave script. GNU Octave, MATLAB, proprietary Engine
|
| 185 |
+
# libraries, license material, and packages are deliberately NOT installed or
|
| 186 |
+
# copied. Without an operator-provided external engine and isolation controls,
|
| 187 |
+
# the API reports UNAVAILABLE.
|
| 188 |
+
COPY szl_numerics_adapter.py ./
|
| 189 |
+
COPY szl_numerics_dataset.py ./
|
| 190 |
+
COPY szl_numerics_experiment.py ./
|
| 191 |
+
COPY numerics/ ./numerics/
|
| 192 |
+
# Wave 23 Yupaq governed computation plane. It ships only the strict routing
|
| 193 |
+
# contract and delegates to already-copied engines; it installs no new runtime,
|
| 194 |
+
# prover, provider SDK, or proprietary dependency.
|
| 195 |
+
COPY szl_yupaq_compute.py ./
|
| 196 |
+
COPY proofs/lean-theorem-tree.json ./proofs/lean-theorem-tree.json
|
| 197 |
+
COPY research/formula-training-admission/admission-manifest.json ./research/formula-training-admission/admission-manifest.json
|
| 198 |
+
COPY data/szl-lake/evidence-manifest.json ./data/szl-lake/evidence-manifest.json
|
| 199 |
+
# Wave 19 formal-conjecture receipt lab. This copies only the strict contract,
|
| 200 |
+
# bounded ledger, and public-key receipt verifier; it installs no prover and
|
| 201 |
+
# exposes no command or network execution path.
|
| 202 |
+
COPY szl_formal_conjecture_lab.py ./
|
| 203 |
+
# M1 experimental model operational gate. Metadata and the status UI are
|
| 204 |
+
# bundled, but model/base/adapter weights are not. A stock image therefore
|
| 205 |
+
# reports UNAVAILABLE until an operator mounts exact local artifacts and the
|
| 206 |
+
# verified local PEFT/GPU runtime; no build-time or request-time download path.
|
| 207 |
+
COPY szl_m1_model_gate.py ./
|
| 208 |
+
COPY szl_m1_corpus_manifest.py ./
|
| 209 |
+
COPY model_release/m1/ ./model_release/m1/
|
| 210 |
+
# Canonical release identity and public Zenodo readback receipt. The readback
|
| 211 |
+
# file ships in a PENDING state until a separately verified archive PR replaces
|
| 212 |
+
# it; the runtime never invents a DOI from the version number.
|
| 213 |
+
COPY szl_release_identity.py ./
|
| 214 |
+
COPY zenodo-readback.json ./
|
| 215 |
+
# Shared fail-closed provider transport. Registry adapters opt in to private
|
| 216 |
+
# destinations explicitly; this module performs pinned DNS validation, bounded
|
| 217 |
+
# redirect handling, response-size limits, and secret-safe deterministic errors.
|
| 218 |
+
COPY szl_provider_http.py ./
|
| 219 |
# Primary official project registry (51 records across 10 fields). Runtime
|
| 220 |
# serves the deterministic, unranked registry; optional live metadata remains a
|
| 221 |
# bounded adapter and is not executed on anonymous public requests.
|
|
|
|
| 706 |
# hf-sync mirrored) — same baked-only pattern as web/sda.html + web/immune.html;
|
| 707 |
# declared in copy-sync-lockstep.json image_only_assets + hf-module-drift-allow.json
|
| 708 |
# accepted_divergences.
|
| 709 |
+
COPY web/formulas.html web/v4_fleet_panel.html web/operator.html web/fleet-c2.html web/living-anatomy.html web/nemo.html web/restraint.html web/restraint-bench.html web/holo.html web/constitution.html web/quant.html web/estate-hologram.html web/hologram.html web/determinacy.html web/verify-receipt.html web/sda.html web/dns.html web/m1-model.html ./web/
|
| 710 |
COPY web/signature-is-not-proof.html ./web/signature-is-not-proof.html
|
| 711 |
COPY web/defense-readiness.html ./web/defense-readiness.html
|
| 712 |
# ADDITIVE (Lane A AGENTIC CORE, Dev A, 2026-06-14; QA9 restore 2026-06): the
|
|
|
|
| 1610 |
# brainqueryaudit.js ships via the existing whole-tree `COPY static/3d/ ./static/3d/`
|
| 1611 |
# above. RECORDS/OBSERVES only — adds NOTHING to the locked-8; Λ = Conjecture 1; trust 0.97.
|
| 1612 |
COPY szl_brainqueryaudit.py ./szl_brainqueryaudit.py
|
| 1613 |
+
# Wave 22: content-addressed corpus admission + fail-closed Brain reranker/feed.
|
| 1614 |
+
# No model weights, trainer, or network harvester are included.
|
| 1615 |
+
COPY szl_braincorpus.py szl_brain_reranker.py ./
|
| 1616 |
# BRAIN LINEAGE (feat/frontier-brainlineage) — NODE-ORIGIN lineage over the SAME
|
| 1617 |
# honest brain graph: for a node id or a query's top nodes it reports HOW each node
|
| 1618 |
# ENTERED the graph, read VERBATIM from the node's OWN real origin fields
|
|
|
|
| 1706 |
ARG SZL_GIT_SHA=unknown
|
| 1707 |
ARG SZL_BUILD_TIME=unknown
|
| 1708 |
ENV SZL_GIT_SHA=${SZL_GIT_SHA} \
|
| 1709 |
+
SZL_BUILD_TIME=${SZL_BUILD_TIME} \
|
| 1710 |
+
A11OY_ORG_RAG_DB=/app/data/a11oy_org_rag.db
|
| 1711 |
+
|
| 1712 |
+
# The Second Brain's SQLite index is rebuildable, but a mounted /app/data keeps
|
| 1713 |
+
# the active generation across process/container replacement. Deployments that
|
| 1714 |
+
# do not attach storage will rebuild and report that fact; they never claim
|
| 1715 |
+
# cross-redeploy durability.
|
| 1716 |
+
VOLUME ["/app/data"]
|
| 1717 |
CMD ["python", "serve.py"]
|
| 1718 |
|
| 1719 |
|
|
@@ -4,8 +4,8 @@ Follows a11oy's module convention: expose `register(app, ns="a11oy") -> str`, mo
|
|
| 4 |
by serve.py inside a try/except guard so a11oy boots unaffected if anything here fails.
|
| 5 |
|
| 6 |
The model backend is a11oy's OWN orchestrator (see ayllu/backend.py): ask/council now
|
| 7 |
-
produce REAL answers when
|
| 8 |
-
honest, clearly-labeled stub otherwise — never a fabricated answer. Cost is bounded:
|
| 9 |
prompt length is capped, council fan-out is capped, and ask/council carry a process-
|
| 10 |
wide rate limit (429 + Retry-After).
|
| 11 |
|
|
@@ -63,12 +63,14 @@ from ayllu import __version__ as _AYLLU_VERSION
|
|
| 63 |
from ayllu import backend as _backend
|
| 64 |
from ayllu.lounge import Lounge
|
| 65 |
from ayllu.loop import run_turn
|
|
|
|
| 66 |
from ayllu.personas import ROSTER, get_persona
|
| 67 |
|
| 68 |
__version__ = _AYLLU_VERSION
|
| 69 |
|
| 70 |
# ---- cost + abuse bounds (public Space; real token cost once live) -----------
|
| 71 |
MAX_PROMPT_CHARS = 6000
|
|
|
|
| 72 |
COUNCIL_MAX = 5 # hard cap on participants / call
|
| 73 |
COUNCIL_DEBATE_MAX = 3 # debate doubles model calls; tighter cap bounds cost
|
| 74 |
ASK_MAX_TOKENS = 384
|
|
@@ -80,11 +82,43 @@ COUNCIL_DEFAULT = ["Amaru", "Kamachiq", "Qhatuq"] # architect · orchestrator
|
|
| 80 |
COUNCIL_CONTRACT_VERSION = "2.0"
|
| 81 |
COUNCIL_SCHEMA = "szl.ayllu.evidence-bound-council/v2"
|
| 82 |
NEMO_ARTIFACT = "https://huggingface.co/SZLHOLDINGS/szl-nemo"
|
|
|
|
| 83 |
|
| 84 |
-
# One process-wide lounge (in-memory, honest source labels).
|
|
|
|
| 85 |
_LOUNGE = Lounge()
|
| 86 |
|
| 87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
class _RateBucket:
|
| 89 |
"""Tiny process-wide sliding-window limiter. Honest: bounds THIS process only."""
|
| 90 |
|
|
@@ -144,7 +178,11 @@ def _make_receipt(payload: Dict[str, Any], sign_fn=None) -> Dict[str, Any]:
|
|
| 144 |
try:
|
| 145 |
env = sign_fn(payload)
|
| 146 |
if isinstance(env, dict):
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
honesty = "UNSIGNED - runtime signer returned a non-object; no signature fabricated."
|
| 149 |
except Exception as exc:
|
| 150 |
honesty = (f"UNSIGNED - runtime signer raised ({str(exc)[:80]}); "
|
|
@@ -277,6 +315,7 @@ def council_manifest(ns: str = "a11oy",
|
|
| 277 |
"outer Council DSSE receipt",
|
| 278 |
],
|
| 279 |
"limits": {
|
|
|
|
| 280 |
"prompt_chars": MAX_PROMPT_CHARS,
|
| 281 |
"participants": COUNCIL_MAX,
|
| 282 |
"debate_participants": COUNCIL_DEBATE_MAX,
|
|
@@ -299,7 +338,7 @@ def council_manifest(ns: str = "a11oy",
|
|
| 299 |
"reproduce": {
|
| 300 |
"manifest": base + "/council/manifest",
|
| 301 |
"verifier": f"/api/{ns}/v1/verify/receipt",
|
| 302 |
-
"public_key":
|
| 303 |
},
|
| 304 |
"nemo": {
|
| 305 |
"artifact": NEMO_ARTIFACT,
|
|
@@ -311,6 +350,8 @@ def council_manifest(ns: str = "a11oy",
|
|
| 311 |
"not SZL-trained weights. Council answers use the live A11OY router."
|
| 312 |
),
|
| 313 |
},
|
|
|
|
|
|
|
| 314 |
"evaluation": {
|
| 315 |
"council_effectiveness": "NOT_MEASURED",
|
| 316 |
"required_next": (
|
|
@@ -350,11 +391,19 @@ def _nemo_council_route(prompt: str, sign_fn=None) -> Dict[str, Any]:
|
|
| 350 |
|
| 351 |
|
| 352 |
def _build_council_contract(prompt: str, result: Dict[str, Any],
|
| 353 |
-
nemo_route: Dict[str, Any]
|
|
|
|
|
|
|
| 354 |
rounds = result.get("rounds") or []
|
| 355 |
turn_evidence = []
|
| 356 |
for turn in rounds:
|
| 357 |
answer = turn.get("answer")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 358 |
turn_evidence.append({
|
| 359 |
"persona": turn.get("persona"),
|
| 360 |
"round": turn.get("round"),
|
|
@@ -365,9 +414,39 @@ def _build_council_contract(prompt: str, result: Dict[str, Any],
|
|
| 365 |
"timeout_s": turn.get("timeout_s"),
|
| 366 |
"correctness_state": ("NOT_APPLICABLE_STUB" if bool(turn.get("stub"))
|
| 367 |
else "UNVERIFIED_MODEL_OUTPUT"),
|
| 368 |
-
"
|
| 369 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
"energy_receipt_sha256": _receipt_sha(turn.get("energy_receipt")),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
})
|
| 372 |
replay_material = {
|
| 373 |
"contract_version": COUNCIL_CONTRACT_VERSION,
|
|
@@ -398,6 +477,8 @@ def _build_council_contract(prompt: str, result: Dict[str, Any],
|
|
| 398 |
"correctness_state": "NOT_VERIFIED",
|
| 399 |
"prompt_sha256": replay_material["prompt_sha256"],
|
| 400 |
"turn_evidence": turn_evidence,
|
|
|
|
|
|
|
| 401 |
"routing": nemo_route,
|
| 402 |
"formula_path": [
|
| 403 |
{"id": "lambda-aggregate", "state": "CONJECTURE_1_ADVISORY"},
|
|
@@ -432,7 +513,7 @@ def _build_council_contract(prompt: str, result: Dict[str, Any],
|
|
| 432 |
"key": "sha256:" + _sha256_json(replay_material),
|
| 433 |
"material": replay_material,
|
| 434 |
"verifier": "/api/a11oy/v1/verify/receipt",
|
| 435 |
-
"public_key":
|
| 436 |
},
|
| 437 |
"training": {
|
| 438 |
"artifact": NEMO_ARTIFACT,
|
|
@@ -526,7 +607,7 @@ radial-gradient(50% 35% at 10% 110%,rgba(212,164,68,.05),transparent 60%)}
|
|
| 526 |
main{max-width:980px;margin:0 auto;padding:36px 22px;position:relative;z-index:1}
|
| 527 |
h1{color:var(--teal);margin:0 0 4px;font-size:26px;display:flex;align-items:center;gap:10px}
|
| 528 |
h2{font-size:16px;margin:0 0 10px;color:var(--fg)}
|
| 529 |
-
.sub{color:var(--dim);margin:0 0 22px}
|
| 530 |
.badge{font-size:11px;font-weight:700;letter-spacing:.04em;padding:3px 8px;border-radius:20px;
|
| 531 |
border:1px solid var(--line);color:var(--dim)}
|
| 532 |
.badge.live{color:#0a1;background:#0a2a17;border-color:#1c5}
|
|
@@ -590,12 +671,13 @@ section[id]{scroll-margin-top:72px}
|
|
| 590 |
.tgl{display:flex;gap:7px;align-items:center;color:var(--dim);font-size:13px;margin:0 0 8px}
|
| 591 |
.tgl input{width:auto}
|
| 592 |
.prov{color:var(--dim);font-size:11px;margin-top:14px;line-height:1.6}
|
|
|
|
| 593 |
@media (max-width:720px){
|
| 594 |
main{padding:24px 14px}
|
| 595 |
.tb-wrap{padding:9px 14px;flex-wrap:nowrap}
|
| 596 |
.tb-brand{flex:0 0 auto}
|
| 597 |
-
.tb-nav{flex:1 1 auto;min-width:0;flex-wrap:nowrap;overflow-x:auto;
|
| 598 |
-
-webkit-overflow-scrolling:touch;scrollbar-width:none}
|
| 599 |
.tb-nav::-webkit-scrollbar{display:none}
|
| 600 |
.tb-nav a{flex:0 0 auto}
|
| 601 |
.card{padding:14px}
|
|
@@ -608,13 +690,14 @@ section[id]{scroll-margin-top:72px}
|
|
| 608 |
</style></head><body>
|
| 609 |
<header class="topbar"><div class="tb-wrap">
|
| 610 |
<a class="tb-brand" href="/ayllu">Ayllu <span id="badge" class="badge">…</span></a>
|
| 611 |
-
<nav class="tb-nav"><a href="#sec-ask">Ask</a><a href="#sec-council">Council</a><a href="#sec-roster">Roster</a><a href="#sec-lounge">Lounge</a><a href="#sec-organism">
|
| 612 |
</div></header>
|
| 613 |
<main>
|
| 614 |
<h1>Ayllu</h1>
|
| 615 |
<p class="sub">The AlloyScape tribe, ingested and reborn as a11oy's own agent community —
|
| 616 |
<span id="count">?</span> personas, one guarded loop. v__VERSION__ ·
|
| 617 |
-
<span title="Curated, cited text appended to every persona's system prompt — no weights changed anywhere.">knowledge instilled, never "trained"</span>
|
|
|
|
| 618 |
|
| 619 |
<section class="card" id="sec-ask">
|
| 620 |
<h2>Ask a persona</h2>
|
|
@@ -649,14 +732,14 @@ section[id]{scroll-margin-top:72px}
|
|
| 649 |
<section class="card" id="sec-roster">
|
| 650 |
<h2>Roster</h2>
|
| 651 |
<table id="roster"><thead><tr><th>Persona</th><th>Quechua</th><th>Archetype</th>
|
| 652 |
-
<th>a11oy domain</th><th>Autonomy</th><th>Knowledge</th></tr></thead><tbody></tbody></table>
|
| 653 |
<div class="src" style="margin-top:6px">"Instilled ✓" = the shared, cited Wave-13 leaders
|
| 654 |
corpus is appended to that persona's system prompt at runtime. No model weights are
|
| 655 |
changed anywhere — this is knowledge instillation, not training.</div>
|
| 656 |
</section>
|
| 657 |
|
| 658 |
<section class="card" id="sec-lounge">
|
| 659 |
-
<h2>
|
| 660 |
<div id="lounge" class="out"></div>
|
| 661 |
</section>
|
| 662 |
|
|
@@ -666,12 +749,14 @@ section[id]{scroll-margin-top:72px}
|
|
| 666 |
organism. These panels read the same governed endpoints as the command centre — an
|
| 667 |
unavailable endpoint says so rather than faking a value.</div>
|
| 668 |
<div class="grid">
|
|
|
|
| 669 |
<div class="panel"><h3>Formulas <span class="small" id="f-badge">…</span></h3><div id="f-out" class="small">loading…</div></div>
|
| 670 |
<div class="panel"><h3>Doctrine lock <span class="small" id="d-badge">…</span></h3><div id="d-out" class="small">loading…</div></div>
|
| 671 |
<div class="panel"><h3>Sovereign energy <span class="small" id="e-badge">…</span></h3><div id="e-out" class="small">loading…</div></div>
|
| 672 |
</div>
|
| 673 |
<div class="links">
|
| 674 |
<a href="/living-anatomy">Living anatomy</a>
|
|
|
|
| 675 |
<a href="/formulas">PURIQ formulas</a>
|
| 676 |
<a href="/wires">The constitution</a>
|
| 677 |
<a href="/api/__NS__/v1/brain/graph" title="Full brain graph JSON (~4 MB)">Brain graph (raw JSON)</a>
|
|
@@ -691,7 +776,8 @@ section[id]{scroll-margin-top:72px}
|
|
| 691 |
<div class="law"><b>Bounded-autonomy law.</b> Every persona runs under a11oy's
|
| 692 |
fail-closed Λ-gate; state-changing actions require two-person attestation. The tribe's
|
| 693 |
"always execute" mandate is deliberately <b>not</b> adopted. Answers come from a11oy's
|
| 694 |
-
own model backend + router; when
|
|
|
|
| 695 |
<code>ask</code>/<code>council</code> return a clearly-labeled stub — never a fabricated
|
| 696 |
answer. Debate mode is bounded to exactly two rounds. These turns do direct completion
|
| 697 |
only (no tool dispatch yet).</div>
|
|
@@ -744,6 +830,9 @@ async function loadRoster(){
|
|
| 744 |
badge.textContent=mode.toUpperCase();
|
| 745 |
badge.className='badge '+(mode==='live'?'live':mode==='stub'?'stub':'warn');
|
| 746 |
badge.title=b.note||'';
|
|
|
|
|
|
|
|
|
|
| 747 |
const sel=document.getElementById('persona'), csel=document.getElementById('councilsel');
|
| 748 |
const rows=[];
|
| 749 |
(data.personas||[]).forEach(p=>{
|
|
@@ -751,8 +840,10 @@ async function loadRoster(){
|
|
| 751 |
o.textContent=p.name+' — '+p.domain;sel.appendChild(o);
|
| 752 |
csel.appendChild(o.cloneNode(true));
|
| 753 |
const kn=p.knowledge_instilled?'instilled ✓':'—';
|
|
|
|
| 754 |
rows.push(`<tr><td>${chip(p.name)} <b>${esc(p.name)}</b></td><td>${esc(p.quechua)}</td>`
|
| 755 |
+`<td>${esc(p.archetype)}</td><td>${esc(p.domain)}</td>`
|
|
|
|
| 756 |
+`<td>${esc(p.autonomy_level)}</td><td class="src">${kn}</td></tr>`);
|
| 757 |
});
|
| 758 |
document.querySelector('#roster tbody').innerHTML=rows.join('');
|
|
@@ -825,6 +916,30 @@ async function loadLounge(){
|
|
| 825 |
document.getElementById('refreshlounge').onclick=loadLounge;
|
| 826 |
function unavailable(el,status){el.innerHTML='<span class="src">endpoint unavailable ('
|
| 827 |
+esc(String(status))+') — shown honestly, not faked.</span>';}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 828 |
async function loadFormulas(){
|
| 829 |
const b=document.getElementById('f-badge'), out=document.getElementById('f-out');
|
| 830 |
const {ok,status,data}=await j(gapi('formulas'));
|
|
@@ -880,7 +995,7 @@ async function loadObs(){
|
|
| 880 |
out.innerHTML='<div class="lg"><b>observability</b><pre class="src" style="white-space:pre-wrap;margin:.3rem 0 0">'
|
| 881 |
+esc(JSON.stringify(data.melt||data,null,2).slice(0,600))+'</pre></div>';
|
| 882 |
}
|
| 883 |
-
loadRoster();loadLounge();loadMesh();loadObs();loadFormulas();loadDoctrine();loadEnergy();
|
| 884 |
</script>
|
| 885 |
</body></html>"""
|
| 886 |
|
|
@@ -910,17 +1025,43 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 910 |
return None
|
| 911 |
|
| 912 |
async def _roster(request: "Request") -> "JSONResponse":
|
|
|
|
| 913 |
return JSONResponse({
|
| 914 |
"count": len(ROSTER),
|
| 915 |
"namespace": ns,
|
| 916 |
-
"personas": [
|
| 917 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
"law": "a11oy bounded-autonomy (fail-closed Λ-gate); the tribe's unbounded "
|
| 919 |
"'always execute' mandate is NOT adopted",
|
| 920 |
"provenance": "ingested from the AlloyScape tribe design; see ayllu/INGEST.md",
|
| 921 |
"version": __version__,
|
| 922 |
})
|
| 923 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 924 |
async def _council_manifest(request: "Request") -> "JSONResponse":
|
| 925 |
storage = getattr(request.app.state, "ayllu_council_khipu_storage",
|
| 926 |
council_storage)
|
|
@@ -933,12 +1074,12 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 933 |
{"error": "rate limited (process-wide ask budget)", "retry_after_s": retry},
|
| 934 |
status_code=429, headers={"Retry-After": str(retry)})
|
| 935 |
try:
|
| 936 |
-
body = await
|
| 937 |
-
except
|
| 938 |
-
return JSONResponse({"error":
|
| 939 |
-
|
| 940 |
-
|
| 941 |
-
|
| 942 |
name = body.get("persona")
|
| 943 |
prompt = body.get("prompt")
|
| 944 |
if not name or not prompt:
|
|
@@ -967,20 +1108,54 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 967 |
|
| 968 |
turn = await run_turn(p, prompt, model_complete=_ask_complete,
|
| 969 |
difficulty=difficulty)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 970 |
ask_id = str(uuid.uuid4())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 971 |
receipt = _make_receipt({
|
| 972 |
"ask_id": ask_id,
|
| 973 |
"persona": p.name,
|
| 974 |
"prompt_sha256": hashlib.sha256(prompt.encode()).hexdigest(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 975 |
"tier_advisory": turn.get("tier", {}).get("route"),
|
| 976 |
"model": turn.get("model"),
|
| 977 |
"stub": turn.get("stub"),
|
| 978 |
"energy_receipt_sha256": _receipt_sha(turn.get("energy_receipt")),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 979 |
"honesty": turn.get("honesty"),
|
| 980 |
}, sign_fn=_runtime_signer(request))
|
| 981 |
-
_LOUNGE.post(
|
| 982 |
-
p.name, turn.get("answer") or turn.get("honesty"),
|
| 983 |
-
source=("brain" if turn.get("answer") is not None else "persona-fallback"))
|
| 984 |
return JSONResponse({"ask_id": ask_id, "turn": turn, "receipt": receipt})
|
| 985 |
|
| 986 |
async def _council(request: "Request") -> "JSONResponse":
|
|
@@ -991,12 +1166,12 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 991 |
"retry_after_s": retry},
|
| 992 |
status_code=429, headers={"Retry-After": str(retry)})
|
| 993 |
try:
|
| 994 |
-
body = await
|
| 995 |
-
except
|
| 996 |
-
return JSONResponse({"error":
|
| 997 |
-
|
| 998 |
-
|
| 999 |
-
|
| 1000 |
prompt = body.get("prompt")
|
| 1001 |
if not prompt:
|
| 1002 |
return JSONResponse({"error": "'prompt' is required"}, status_code=422)
|
|
@@ -1033,13 +1208,14 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 1033 |
timeout_s=COUNCIL_TURN_TIMEOUT_S)
|
| 1034 |
|
| 1035 |
result = await _LOUNGE.deliberate(
|
| 1036 |
-
prompt, personas, model_complete=_council_complete, debate=debate
|
|
|
|
| 1037 |
if cap_note:
|
| 1038 |
result["cap_note"] = cap_note
|
| 1039 |
council_id = str(uuid.uuid4())
|
| 1040 |
signer = _runtime_signer(request)
|
| 1041 |
nemo_route = _nemo_council_route(prompt, sign_fn=signer)
|
| 1042 |
-
contract = _build_council_contract(prompt, result, nemo_route)
|
| 1043 |
store = getattr(request.app.state, "ayllu_council_khipu", council_store)
|
| 1044 |
storage = getattr(request.app.state, "ayllu_council_khipu_storage",
|
| 1045 |
council_storage)
|
|
@@ -1055,6 +1231,8 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 1055 |
"evidence_state": contract["evidence_state"],
|
| 1056 |
"replay_key": contract["replay"]["key"],
|
| 1057 |
"turn_evidence": contract["turn_evidence"],
|
|
|
|
|
|
|
| 1058 |
"nemo_route_receipt_sha256": _receipt_sha(
|
| 1059 |
(contract.get("routing") or {}).get("receipt")),
|
| 1060 |
"human_checkpoint": contract["human_checkpoint"],
|
|
@@ -1079,6 +1257,12 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 1079 |
app.add_api_route(f"/api/{ns}/v1/ayllu/roster", _roster, methods=["GET"],
|
| 1080 |
tags=["ayllu"],
|
| 1081 |
summary="a11oy-native agent roster + live/stub backend status")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1082 |
app.add_api_route(f"/api/{ns}/v1/ayllu/ask", _ask, methods=["POST"],
|
| 1083 |
tags=["ayllu"],
|
| 1084 |
summary="Ask one persona — bounded, honest, receipted")
|
|
@@ -1089,13 +1273,13 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 1089 |
tags=["ayllu"],
|
| 1090 |
summary="Bounded multi-persona deliberation (capped fan-out; optional 2-round debate mode after arXiv:2305.14325)")
|
| 1091 |
app.add_api_route(f"/api/{ns}/v1/ayllu/lounge", _lounge_feed, methods=["GET"],
|
| 1092 |
-
tags=["ayllu"], summary="
|
| 1093 |
app.add_api_route("/ayllu", _page, methods=["GET"], include_in_schema=False)
|
| 1094 |
|
| 1095 |
return (
|
| 1096 |
f"ok — ayllu registered: {len(ROSTER)} personas; live model backend "
|
| 1097 |
f"({_backend.backend_status().get('mode')}); bounded-autonomy Λ-gate; "
|
| 1098 |
-
f"/ayllu + /api/{ns}/v1/ayllu/roster|ask|council|lounge; "
|
| 1099 |
f"debate-mode council; council_khipu={council_storage.get('backend')} "
|
| 1100 |
f"(process_restart_durable={council_storage.get('durable')}, "
|
| 1101 |
f"redeploy=NOT_VERIFIED); version={__version__}"
|
|
|
|
| 4 |
by serve.py inside a try/except guard so a11oy boots unaffected if anything here fails.
|
| 5 |
|
| 6 |
The model backend is a11oy's OWN orchestrator (see ayllu/backend.py): ask/council now
|
| 7 |
+
produce REAL answers when a reachable local endpoint or credentialed remote provider
|
| 8 |
+
is available, and an honest, clearly-labeled stub otherwise — never a fabricated answer. Cost is bounded:
|
| 9 |
prompt length is capped, council fan-out is capped, and ask/council carry a process-
|
| 10 |
wide rate limit (429 + Retry-After).
|
| 11 |
|
|
|
|
| 63 |
from ayllu import backend as _backend
|
| 64 |
from ayllu.lounge import Lounge
|
| 65 |
from ayllu.loop import run_turn
|
| 66 |
+
from ayllu.model_binding import family_binding, persona_binding, second_brain_binding
|
| 67 |
from ayllu.personas import ROSTER, get_persona
|
| 68 |
|
| 69 |
__version__ = _AYLLU_VERSION
|
| 70 |
|
| 71 |
# ---- cost + abuse bounds (public Space; real token cost once live) -----------
|
| 72 |
MAX_PROMPT_CHARS = 6000
|
| 73 |
+
MAX_BODY_BYTES = 24 * 1024
|
| 74 |
COUNCIL_MAX = 5 # hard cap on participants / call
|
| 75 |
COUNCIL_DEBATE_MAX = 3 # debate doubles model calls; tighter cap bounds cost
|
| 76 |
ASK_MAX_TOKENS = 384
|
|
|
|
| 82 |
COUNCIL_CONTRACT_VERSION = "2.0"
|
| 83 |
COUNCIL_SCHEMA = "szl.ayllu.evidence-bound-council/v2"
|
| 84 |
NEMO_ARTIFACT = "https://huggingface.co/SZLHOLDINGS/szl-nemo"
|
| 85 |
+
RUNTIME_VERIFY_KEY_URL = "/api/a11oy/cosign.pub"
|
| 86 |
|
| 87 |
+
# One process-wide opt-in lounge (in-memory, honest source labels). Public ask and
|
| 88 |
+
# council handlers do not automatically publish caller output into it.
|
| 89 |
_LOUNGE = Lounge()
|
| 90 |
|
| 91 |
|
| 92 |
+
class _BodyTooLarge(ValueError):
|
| 93 |
+
pass
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
async def _bounded_json_body(request: "Request") -> Dict[str, Any]:
|
| 97 |
+
"""Read one bounded JSON object before any paid inference is attempted."""
|
| 98 |
+
declared = request.headers.get("content-length")
|
| 99 |
+
if declared is not None:
|
| 100 |
+
try:
|
| 101 |
+
size = int(declared)
|
| 102 |
+
except ValueError as exc:
|
| 103 |
+
raise ValueError("invalid content-length") from exc
|
| 104 |
+
if size < 0:
|
| 105 |
+
raise ValueError("invalid content-length")
|
| 106 |
+
if size > MAX_BODY_BYTES:
|
| 107 |
+
raise _BodyTooLarge(f"request body exceeds {MAX_BODY_BYTES} bytes")
|
| 108 |
+
data = bytearray()
|
| 109 |
+
async for chunk in request.stream():
|
| 110 |
+
if len(data) + len(chunk) > MAX_BODY_BYTES:
|
| 111 |
+
raise _BodyTooLarge(f"request body exceeds {MAX_BODY_BYTES} bytes")
|
| 112 |
+
data.extend(chunk)
|
| 113 |
+
try:
|
| 114 |
+
value = json.loads(bytes(data).decode("utf-8"))
|
| 115 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 116 |
+
raise ValueError("invalid JSON body") from exc
|
| 117 |
+
if not isinstance(value, dict):
|
| 118 |
+
raise ValueError("request body must be a JSON object")
|
| 119 |
+
return value
|
| 120 |
+
|
| 121 |
+
|
| 122 |
class _RateBucket:
|
| 123 |
"""Tiny process-wide sliding-window limiter. Honest: bounds THIS process only."""
|
| 124 |
|
|
|
|
| 178 |
try:
|
| 179 |
env = sign_fn(payload)
|
| 180 |
if isinstance(env, dict):
|
| 181 |
+
out = dict(env)
|
| 182 |
+
out.setdefault("verify_key_url", RUNTIME_VERIFY_KEY_URL)
|
| 183 |
+
out.setdefault("key_scope", "PROCESS_BOOT_EPHEMERAL")
|
| 184 |
+
out.setdefault("key_lifetime", "UNTIL_PROCESS_RESTART")
|
| 185 |
+
return out
|
| 186 |
honesty = "UNSIGNED - runtime signer returned a non-object; no signature fabricated."
|
| 187 |
except Exception as exc:
|
| 188 |
honesty = (f"UNSIGNED - runtime signer raised ({str(exc)[:80]}); "
|
|
|
|
| 315 |
"outer Council DSSE receipt",
|
| 316 |
],
|
| 317 |
"limits": {
|
| 318 |
+
"request_body_bytes": MAX_BODY_BYTES,
|
| 319 |
"prompt_chars": MAX_PROMPT_CHARS,
|
| 320 |
"participants": COUNCIL_MAX,
|
| 321 |
"debate_participants": COUNCIL_DEBATE_MAX,
|
|
|
|
| 338 |
"reproduce": {
|
| 339 |
"manifest": base + "/council/manifest",
|
| 340 |
"verifier": f"/api/{ns}/v1/verify/receipt",
|
| 341 |
+
"public_key": RUNTIME_VERIFY_KEY_URL,
|
| 342 |
},
|
| 343 |
"nemo": {
|
| 344 |
"artifact": NEMO_ARTIFACT,
|
|
|
|
| 350 |
"not SZL-trained weights. Council answers use the live A11OY router."
|
| 351 |
),
|
| 352 |
},
|
| 353 |
+
"model_family": family_binding(
|
| 354 |
+
namespace=ns, backend_status=_backend.backend_status()),
|
| 355 |
"evaluation": {
|
| 356 |
"council_effectiveness": "NOT_MEASURED",
|
| 357 |
"required_next": (
|
|
|
|
| 391 |
|
| 392 |
|
| 393 |
def _build_council_contract(prompt: str, result: Dict[str, Any],
|
| 394 |
+
nemo_route: Dict[str, Any],
|
| 395 |
+
ns: str = "a11oy") -> Dict[str, Any]:
|
| 396 |
+
family = family_binding(namespace=ns, backend_status=_backend.backend_status())
|
| 397 |
rounds = result.get("rounds") or []
|
| 398 |
turn_evidence = []
|
| 399 |
for turn in rounds:
|
| 400 |
answer = turn.get("answer")
|
| 401 |
+
honesty = turn.get("honesty")
|
| 402 |
+
grounding = turn.get("grounding") if isinstance(
|
| 403 |
+
turn.get("grounding"), dict) else {}
|
| 404 |
+
citation_validation = grounding.get("citation_validation")
|
| 405 |
+
answer_sha = (hashlib.sha256(answer.encode("utf-8")).hexdigest()
|
| 406 |
+
if isinstance(answer, str) else None)
|
| 407 |
turn_evidence.append({
|
| 408 |
"persona": turn.get("persona"),
|
| 409 |
"round": turn.get("round"),
|
|
|
|
| 414 |
"timeout_s": turn.get("timeout_s"),
|
| 415 |
"correctness_state": ("NOT_APPLICABLE_STUB" if bool(turn.get("stub"))
|
| 416 |
else "UNVERIFIED_MODEL_OUTPUT"),
|
| 417 |
+
"answer_present": answer is not None,
|
| 418 |
+
"answer_sha256": answer_sha,
|
| 419 |
+
"output_sha256": answer_sha,
|
| 420 |
+
"honesty_sha256": (hashlib.sha256(str(honesty).encode("utf-8")).hexdigest()
|
| 421 |
+
if honesty is not None else None),
|
| 422 |
+
"turn_output_sha256": _sha256_json({
|
| 423 |
+
"answer": answer,
|
| 424 |
+
"honesty": honesty,
|
| 425 |
+
"stub": bool(turn.get("stub")),
|
| 426 |
+
"timeout": bool(turn.get("timeout", False)),
|
| 427 |
+
"model": turn.get("model"),
|
| 428 |
+
}),
|
| 429 |
"energy_receipt_sha256": _receipt_sha(turn.get("energy_receipt")),
|
| 430 |
+
"model_binding": turn.get("model_binding"),
|
| 431 |
+
"model_binding_sha256": (
|
| 432 |
+
_sha256_json(turn["model_binding"])
|
| 433 |
+
if isinstance(turn.get("model_binding"), dict) else None
|
| 434 |
+
),
|
| 435 |
+
"model_attestation_sha256": (
|
| 436 |
+
turn.get("model_binding", {}).get("model_attestation_sha256")
|
| 437 |
+
if isinstance(turn.get("model_binding"), dict) else None
|
| 438 |
+
),
|
| 439 |
+
"grounding_sha256": (
|
| 440 |
+
turn.get("model_binding", {}).get("grounding_sha256")
|
| 441 |
+
if isinstance(turn.get("model_binding"), dict) else None
|
| 442 |
+
),
|
| 443 |
+
"evidence_set_sha256": grounding.get("evidence_set_sha256"),
|
| 444 |
+
"handles_sha256": grounding.get("handles_sha256"),
|
| 445 |
+
"augmented_prompt_sha256": grounding.get("augmented_prompt_sha256"),
|
| 446 |
+
"citation_validation_sha256": (
|
| 447 |
+
_sha256_json(citation_validation)
|
| 448 |
+
if isinstance(citation_validation, dict) else None
|
| 449 |
+
),
|
| 450 |
})
|
| 451 |
replay_material = {
|
| 452 |
"contract_version": COUNCIL_CONTRACT_VERSION,
|
|
|
|
| 477 |
"correctness_state": "NOT_VERIFIED",
|
| 478 |
"prompt_sha256": replay_material["prompt_sha256"],
|
| 479 |
"turn_evidence": turn_evidence,
|
| 480 |
+
"model_family": family,
|
| 481 |
+
"model_family_binding_sha256": _sha256_json(family),
|
| 482 |
"routing": nemo_route,
|
| 483 |
"formula_path": [
|
| 484 |
{"id": "lambda-aggregate", "state": "CONJECTURE_1_ADVISORY"},
|
|
|
|
| 513 |
"key": "sha256:" + _sha256_json(replay_material),
|
| 514 |
"material": replay_material,
|
| 515 |
"verifier": "/api/a11oy/v1/verify/receipt",
|
| 516 |
+
"public_key": RUNTIME_VERIFY_KEY_URL,
|
| 517 |
},
|
| 518 |
"training": {
|
| 519 |
"artifact": NEMO_ARTIFACT,
|
|
|
|
| 607 |
main{max-width:980px;margin:0 auto;padding:36px 22px;position:relative;z-index:1}
|
| 608 |
h1{color:var(--teal);margin:0 0 4px;font-size:26px;display:flex;align-items:center;gap:10px}
|
| 609 |
h2{font-size:16px;margin:0 0 10px;color:var(--fg)}
|
| 610 |
+
.sub,#family{color:var(--dim);margin:0 0 22px;min-width:0;overflow-wrap:anywhere}
|
| 611 |
.badge{font-size:11px;font-weight:700;letter-spacing:.04em;padding:3px 8px;border-radius:20px;
|
| 612 |
border:1px solid var(--line);color:var(--dim)}
|
| 613 |
.badge.live{color:#0a1;background:#0a2a17;border-color:#1c5}
|
|
|
|
| 671 |
.tgl{display:flex;gap:7px;align-items:center;color:var(--dim);font-size:13px;margin:0 0 8px}
|
| 672 |
.tgl input{width:auto}
|
| 673 |
.prov{color:var(--dim);font-size:11px;margin-top:14px;line-height:1.6}
|
| 674 |
+
.small,.src,.contract,.rcpt,.prov,.ans{min-width:0;overflow-wrap:anywhere}
|
| 675 |
@media (max-width:720px){
|
| 676 |
main{padding:24px 14px}
|
| 677 |
.tb-wrap{padding:9px 14px;flex-wrap:nowrap}
|
| 678 |
.tb-brand{flex:0 0 auto}
|
| 679 |
+
.tb-nav{flex:1 1 auto;min-width:0;max-width:100%;flex-wrap:nowrap;overflow-x:auto;
|
| 680 |
+
-webkit-overflow-scrolling:touch;scrollbar-width:none;overscroll-behavior-inline:contain}
|
| 681 |
.tb-nav::-webkit-scrollbar{display:none}
|
| 682 |
.tb-nav a{flex:0 0 auto}
|
| 683 |
.card{padding:14px}
|
|
|
|
| 690 |
</style></head><body>
|
| 691 |
<header class="topbar"><div class="tb-wrap">
|
| 692 |
<a class="tb-brand" href="/ayllu">Ayllu <span id="badge" class="badge">…</span></a>
|
| 693 |
+
<nav class="tb-nav" aria-label="Ayllu sections"><a href="#sec-ask">Ask</a><a href="#sec-council">Council</a><a href="#sec-roster">Roster</a><a href="#sec-lounge">Lounge</a><a href="#sec-organism">Second Brain</a><a href="#sec-mesh">Mesh</a><a class="tb-home" href="/console" title="Back to the a11oy command centre">← a11oy command centre</a></nav>
|
| 694 |
</div></header>
|
| 695 |
<main>
|
| 696 |
<h1>Ayllu</h1>
|
| 697 |
<p class="sub">The AlloyScape tribe, ingested and reborn as a11oy's own agent community —
|
| 698 |
<span id="count">?</span> personas, one guarded loop. v__VERSION__ ·
|
| 699 |
+
<span title="Curated, cited text appended to every persona's system prompt — no weights changed anywhere.">knowledge instilled, never "trained"</span> ·
|
| 700 |
+
<span id="family">model binding loading</span></p>
|
| 701 |
|
| 702 |
<section class="card" id="sec-ask">
|
| 703 |
<h2>Ask a persona</h2>
|
|
|
|
| 732 |
<section class="card" id="sec-roster">
|
| 733 |
<h2>Roster</h2>
|
| 734 |
<table id="roster"><thead><tr><th>Persona</th><th>Quechua</th><th>Archetype</th>
|
| 735 |
+
<th>a11oy domain</th><th>Forge intent</th><th>Autonomy</th><th>Knowledge</th></tr></thead><tbody></tbody></table>
|
| 736 |
<div class="src" style="margin-top:6px">"Instilled ✓" = the shared, cited Wave-13 leaders
|
| 737 |
corpus is appended to that persona's system prompt at runtime. No model weights are
|
| 738 |
changed anywhere — this is knowledge instillation, not training.</div>
|
| 739 |
</section>
|
| 740 |
|
| 741 |
<section class="card" id="sec-lounge">
|
| 742 |
+
<h2>Opt-in lounge <button id="refreshlounge" class="mini">refresh</button></h2>
|
| 743 |
<div id="lounge" class="out"></div>
|
| 744 |
</section>
|
| 745 |
|
|
|
|
| 749 |
organism. These panels read the same governed endpoints as the command centre — an
|
| 750 |
unavailable endpoint says so rather than faking a value.</div>
|
| 751 |
<div class="grid">
|
| 752 |
+
<div class="panel"><h3>Khipu Second Brain <span class="small" id="sb-badge">…</span></h3><div id="sb-out" class="small">loading…</div></div>
|
| 753 |
<div class="panel"><h3>Formulas <span class="small" id="f-badge">…</span></h3><div id="f-out" class="small">loading…</div></div>
|
| 754 |
<div class="panel"><h3>Doctrine lock <span class="small" id="d-badge">…</span></h3><div id="d-out" class="small">loading…</div></div>
|
| 755 |
<div class="panel"><h3>Sovereign energy <span class="small" id="e-badge">…</span></h3><div id="e-out" class="small">loading…</div></div>
|
| 756 |
</div>
|
| 757 |
<div class="links">
|
| 758 |
<a href="/living-anatomy">Living anatomy</a>
|
| 759 |
+
<a href="/api/__NS__/v1/ayllu/second-brain">Second Brain contract</a>
|
| 760 |
<a href="/formulas">PURIQ formulas</a>
|
| 761 |
<a href="/wires">The constitution</a>
|
| 762 |
<a href="/api/__NS__/v1/brain/graph" title="Full brain graph JSON (~4 MB)">Brain graph (raw JSON)</a>
|
|
|
|
| 776 |
<div class="law"><b>Bounded-autonomy law.</b> Every persona runs under a11oy's
|
| 777 |
fail-closed Λ-gate; state-changing actions require two-person attestation. The tribe's
|
| 778 |
"always execute" mandate is deliberately <b>not</b> adopted. Answers come from a11oy's
|
| 779 |
+
own model backend + router; when neither a reachable local backend nor a remote
|
| 780 |
+
inference credential is available,
|
| 781 |
<code>ask</code>/<code>council</code> return a clearly-labeled stub — never a fabricated
|
| 782 |
answer. Debate mode is bounded to exactly two rounds. These turns do direct completion
|
| 783 |
only (no tool dispatch yet).</div>
|
|
|
|
| 830 |
badge.textContent=mode.toUpperCase();
|
| 831 |
badge.className='badge '+(mode==='live'?'live':mode==='stub'?'stub':'warn');
|
| 832 |
badge.title=b.note||'';
|
| 833 |
+
const mf=data.model_family||{}, family=document.getElementById('family');
|
| 834 |
+
family.textContent=(mf.family_id||'model family unknown')+' · '+(mf.binding_state||'UNAVAILABLE');
|
| 835 |
+
family.title='Profile intent only. The actual model is named by each turn receipt.';
|
| 836 |
const sel=document.getElementById('persona'), csel=document.getElementById('councilsel');
|
| 837 |
const rows=[];
|
| 838 |
(data.personas||[]).forEach(p=>{
|
|
|
|
| 840 |
o.textContent=p.name+' — '+p.domain;sel.appendChild(o);
|
| 841 |
csel.appendChild(o.cloneNode(true));
|
| 842 |
const kn=p.knowledge_instilled?'instilled ✓':'—';
|
| 843 |
+
const mb=p.model_binding||{};
|
| 844 |
rows.push(`<tr><td>${chip(p.name)} <b>${esc(p.name)}</b></td><td>${esc(p.quechua)}</td>`
|
| 845 |
+`<td>${esc(p.archetype)}</td><td>${esc(p.domain)}</td>`
|
| 846 |
+
+`<td>${esc(mb.primary_profile||'UNBOUND')}</td>`
|
| 847 |
+`<td>${esc(p.autonomy_level)}</td><td class="src">${kn}</td></tr>`);
|
| 848 |
});
|
| 849 |
document.querySelector('#roster tbody').innerHTML=rows.join('');
|
|
|
|
| 916 |
document.getElementById('refreshlounge').onclick=loadLounge;
|
| 917 |
function unavailable(el,status){el.innerHTML='<span class="src">endpoint unavailable ('
|
| 918 |
+esc(String(status))+') — shown honestly, not faked.</span>';}
|
| 919 |
+
async function loadSecondBrain(){
|
| 920 |
+
const badge=document.getElementById('sb-badge'), out=document.getElementById('sb-out');
|
| 921 |
+
const {ok,status,data}=await j(api('second-brain'));
|
| 922 |
+
if(!ok){badge.textContent='offline';unavailable(out,status);return;}
|
| 923 |
+
const ready=!!data.ready_for_grounded_navigation;
|
| 924 |
+
const profile=data.profile||{}, memory=data.memory||{}, training=data.training_boundary||{};
|
| 925 |
+
badge.textContent=ready?'ready':'gated';
|
| 926 |
+
out.innerHTML='<div class="kpi">'+esc(ready?'GROUNDED':'NOT READY')+'</div>'
|
| 927 |
+
+'<div class="small">'+esc(data.system_id||'SZL-Khipu-Second-Brain-v1')+'</div>'
|
| 928 |
+
+'<div class="lg small">model '+esc(profile.served_model||profile.expected_model||'unavailable')
|
| 929 |
+
+' · exact tag '+esc(profile.exact_tag_observed?'observed':'missing')+'</div>'
|
| 930 |
+
+'<div class="lg small">memory '+esc(memory.built?'built':'not built')
|
| 931 |
+
+' · '+esc(String(memory.document_count??'—'))+' docs · '
|
| 932 |
+
+esc(String(memory.chunk_count??'—'))+' chunks · '
|
| 933 |
+
+esc(String(memory.node_count??'—'))+' graph nodes</div>'
|
| 934 |
+
+'<div class="lg small">Brain handles '+esc(String(memory.brain_handle_count??0))
|
| 935 |
+
+' · gradient authority '+esc(String(memory.training_authority_rows??0))
|
| 936 |
+
+' · integrity '+esc(memory.integrity_state||memory.rehydration_state||'not evaluated')+'</div>'
|
| 937 |
+
+'<div class="lg small">gradient admission '
|
| 938 |
+
+esc(String(training.raw_brain_nodes_admitted_to_gradients??0))+' / '
|
| 939 |
+
+esc(String(training.raw_brain_nodes_observed??'—'))
|
| 940 |
+
+' · '+esc(data.promotion_state||data.state||'UNKNOWN')+'</div>'
|
| 941 |
+
+'<div class="src" style="margin-top:6px">Compound model: navigator + persistent evidence memory + governed controller + receipts. Indexed nodes are not mislabeled as weights.</div>';
|
| 942 |
+
}
|
| 943 |
async function loadFormulas(){
|
| 944 |
const b=document.getElementById('f-badge'), out=document.getElementById('f-out');
|
| 945 |
const {ok,status,data}=await j(gapi('formulas'));
|
|
|
|
| 995 |
out.innerHTML='<div class="lg"><b>observability</b><pre class="src" style="white-space:pre-wrap;margin:.3rem 0 0">'
|
| 996 |
+esc(JSON.stringify(data.melt||data,null,2).slice(0,600))+'</pre></div>';
|
| 997 |
}
|
| 998 |
+
loadRoster();loadLounge();loadMesh();loadObs();loadSecondBrain();loadFormulas();loadDoctrine();loadEnergy();
|
| 999 |
</script>
|
| 1000 |
</body></html>"""
|
| 1001 |
|
|
|
|
| 1025 |
return None
|
| 1026 |
|
| 1027 |
async def _roster(request: "Request") -> "JSONResponse":
|
| 1028 |
+
backend = _backend.backend_status()
|
| 1029 |
return JSONResponse({
|
| 1030 |
"count": len(ROSTER),
|
| 1031 |
"namespace": ns,
|
| 1032 |
+
"personas": [
|
| 1033 |
+
{**p.metadata(), "model_binding": persona_binding(p.name)}
|
| 1034 |
+
for p in ROSTER
|
| 1035 |
+
],
|
| 1036 |
+
"backend": backend,
|
| 1037 |
+
"model_family": family_binding(namespace=ns, backend_status=backend),
|
| 1038 |
"law": "a11oy bounded-autonomy (fail-closed Λ-gate); the tribe's unbounded "
|
| 1039 |
"'always execute' mandate is NOT adopted",
|
| 1040 |
"provenance": "ingested from the AlloyScape tribe design; see ayllu/INGEST.md",
|
| 1041 |
"version": __version__,
|
| 1042 |
})
|
| 1043 |
|
| 1044 |
+
async def _model_binding(request: "Request") -> "JSONResponse":
|
| 1045 |
+
return JSONResponse(family_binding(
|
| 1046 |
+
namespace=ns, backend_status=_backend.backend_status()))
|
| 1047 |
+
|
| 1048 |
+
async def _second_brain(request: "Request") -> "JSONResponse":
|
| 1049 |
+
try:
|
| 1050 |
+
import a11oy_org_rag as _org_rag
|
| 1051 |
+
rag = _org_rag.status()
|
| 1052 |
+
except Exception as exc:
|
| 1053 |
+
rag = {
|
| 1054 |
+
"built": False,
|
| 1055 |
+
"state": "UNAVAILABLE",
|
| 1056 |
+
"honesty": f"Brain status unavailable ({type(exc).__name__})",
|
| 1057 |
+
}
|
| 1058 |
+
return JSONResponse(second_brain_binding(
|
| 1059 |
+
namespace=ns,
|
| 1060 |
+
backend_status=_backend.backend_status(),
|
| 1061 |
+
rag_status=rag,
|
| 1062 |
+
signer_ready=callable(getattr(request.app.state, "szl_sign_receipt", None)),
|
| 1063 |
+
))
|
| 1064 |
+
|
| 1065 |
async def _council_manifest(request: "Request") -> "JSONResponse":
|
| 1066 |
storage = getattr(request.app.state, "ayllu_council_khipu_storage",
|
| 1067 |
council_storage)
|
|
|
|
| 1074 |
{"error": "rate limited (process-wide ask budget)", "retry_after_s": retry},
|
| 1075 |
status_code=429, headers={"Retry-After": str(retry)})
|
| 1076 |
try:
|
| 1077 |
+
body = await _bounded_json_body(request)
|
| 1078 |
+
except _BodyTooLarge as exc:
|
| 1079 |
+
return JSONResponse({"error": str(exc), "max_bytes": MAX_BODY_BYTES},
|
| 1080 |
+
status_code=413)
|
| 1081 |
+
except ValueError as exc:
|
| 1082 |
+
return JSONResponse({"error": str(exc)}, status_code=400)
|
| 1083 |
name = body.get("persona")
|
| 1084 |
prompt = body.get("prompt")
|
| 1085 |
if not name or not prompt:
|
|
|
|
| 1108 |
|
| 1109 |
turn = await run_turn(p, prompt, model_complete=_ask_complete,
|
| 1110 |
difficulty=difficulty)
|
| 1111 |
+
binding = turn["model_binding"]
|
| 1112 |
+
grounding = turn.get("grounding") if isinstance(
|
| 1113 |
+
turn.get("grounding"), dict) else {}
|
| 1114 |
+
citation_validation = grounding.get("citation_validation")
|
| 1115 |
ask_id = str(uuid.uuid4())
|
| 1116 |
+
# Bind the answer and honesty channels independently. None means no
|
| 1117 |
+
# answer; an empty string is a present answer and hashes as SHA256("").
|
| 1118 |
+
answer = turn.get("answer")
|
| 1119 |
+
honesty = turn.get("honesty")
|
| 1120 |
+
answer_sha = (hashlib.sha256(answer.encode("utf-8")).hexdigest()
|
| 1121 |
+
if isinstance(answer, str) else None)
|
| 1122 |
+
honesty_sha = (hashlib.sha256(str(honesty).encode("utf-8")).hexdigest()
|
| 1123 |
+
if honesty is not None else None)
|
| 1124 |
+
turn_output_sha = _sha256_json({
|
| 1125 |
+
"answer": answer,
|
| 1126 |
+
"honesty": honesty,
|
| 1127 |
+
"stub": bool(turn.get("stub")),
|
| 1128 |
+
"timeout": bool(turn.get("timeout", False)),
|
| 1129 |
+
"model": turn.get("model"),
|
| 1130 |
+
})
|
| 1131 |
receipt = _make_receipt({
|
| 1132 |
"ask_id": ask_id,
|
| 1133 |
"persona": p.name,
|
| 1134 |
"prompt_sha256": hashlib.sha256(prompt.encode()).hexdigest(),
|
| 1135 |
+
"answer_present": answer is not None,
|
| 1136 |
+
"answer_sha256": answer_sha,
|
| 1137 |
+
"output_sha256": answer_sha,
|
| 1138 |
+
"honesty_sha256": honesty_sha,
|
| 1139 |
+
"turn_output_sha256": turn_output_sha,
|
| 1140 |
"tier_advisory": turn.get("tier", {}).get("route"),
|
| 1141 |
"model": turn.get("model"),
|
| 1142 |
"stub": turn.get("stub"),
|
| 1143 |
"energy_receipt_sha256": _receipt_sha(turn.get("energy_receipt")),
|
| 1144 |
+
"family_id": binding["family_id"],
|
| 1145 |
+
"profile_intent": binding["primary_profile"],
|
| 1146 |
+
"binding_state": binding["binding_state"],
|
| 1147 |
+
"model_binding_sha256": _sha256_json(binding),
|
| 1148 |
+
"model_attestation_sha256": binding.get("model_attestation_sha256"),
|
| 1149 |
+
"grounding_sha256": binding.get("grounding_sha256"),
|
| 1150 |
+
"evidence_set_sha256": grounding.get("evidence_set_sha256"),
|
| 1151 |
+
"handles_sha256": grounding.get("handles_sha256"),
|
| 1152 |
+
"augmented_prompt_sha256": grounding.get("augmented_prompt_sha256"),
|
| 1153 |
+
"citation_validation_sha256": (
|
| 1154 |
+
_sha256_json(citation_validation)
|
| 1155 |
+
if isinstance(citation_validation, dict) else None
|
| 1156 |
+
),
|
| 1157 |
"honesty": turn.get("honesty"),
|
| 1158 |
}, sign_fn=_runtime_signer(request))
|
|
|
|
|
|
|
|
|
|
| 1159 |
return JSONResponse({"ask_id": ask_id, "turn": turn, "receipt": receipt})
|
| 1160 |
|
| 1161 |
async def _council(request: "Request") -> "JSONResponse":
|
|
|
|
| 1166 |
"retry_after_s": retry},
|
| 1167 |
status_code=429, headers={"Retry-After": str(retry)})
|
| 1168 |
try:
|
| 1169 |
+
body = await _bounded_json_body(request)
|
| 1170 |
+
except _BodyTooLarge as exc:
|
| 1171 |
+
return JSONResponse({"error": str(exc), "max_bytes": MAX_BODY_BYTES},
|
| 1172 |
+
status_code=413)
|
| 1173 |
+
except ValueError as exc:
|
| 1174 |
+
return JSONResponse({"error": str(exc)}, status_code=400)
|
| 1175 |
prompt = body.get("prompt")
|
| 1176 |
if not prompt:
|
| 1177 |
return JSONResponse({"error": "'prompt' is required"}, status_code=422)
|
|
|
|
| 1208 |
timeout_s=COUNCIL_TURN_TIMEOUT_S)
|
| 1209 |
|
| 1210 |
result = await _LOUNGE.deliberate(
|
| 1211 |
+
prompt, personas, model_complete=_council_complete, debate=debate,
|
| 1212 |
+
publish_to_lounge=False)
|
| 1213 |
if cap_note:
|
| 1214 |
result["cap_note"] = cap_note
|
| 1215 |
council_id = str(uuid.uuid4())
|
| 1216 |
signer = _runtime_signer(request)
|
| 1217 |
nemo_route = _nemo_council_route(prompt, sign_fn=signer)
|
| 1218 |
+
contract = _build_council_contract(prompt, result, nemo_route, ns=ns)
|
| 1219 |
store = getattr(request.app.state, "ayllu_council_khipu", council_store)
|
| 1220 |
storage = getattr(request.app.state, "ayllu_council_khipu_storage",
|
| 1221 |
council_storage)
|
|
|
|
| 1231 |
"evidence_state": contract["evidence_state"],
|
| 1232 |
"replay_key": contract["replay"]["key"],
|
| 1233 |
"turn_evidence": contract["turn_evidence"],
|
| 1234 |
+
"model_family_binding_sha256": contract[
|
| 1235 |
+
"model_family_binding_sha256"],
|
| 1236 |
"nemo_route_receipt_sha256": _receipt_sha(
|
| 1237 |
(contract.get("routing") or {}).get("receipt")),
|
| 1238 |
"human_checkpoint": contract["human_checkpoint"],
|
|
|
|
| 1257 |
app.add_api_route(f"/api/{ns}/v1/ayllu/roster", _roster, methods=["GET"],
|
| 1258 |
tags=["ayllu"],
|
| 1259 |
summary="a11oy-native agent roster + live/stub backend status")
|
| 1260 |
+
app.add_api_route(f"/api/{ns}/v1/ayllu/model-binding", _model_binding,
|
| 1261 |
+
methods=["GET"], tags=["ayllu"],
|
| 1262 |
+
summary="Honest SZL-Forge family and Yupaq proposal binding")
|
| 1263 |
+
app.add_api_route(f"/api/{ns}/v1/ayllu/second-brain", _second_brain,
|
| 1264 |
+
methods=["GET"], tags=["ayllu"],
|
| 1265 |
+
summary="Khipu compound Second Brain runtime and training boundary")
|
| 1266 |
app.add_api_route(f"/api/{ns}/v1/ayllu/ask", _ask, methods=["POST"],
|
| 1267 |
tags=["ayllu"],
|
| 1268 |
summary="Ask one persona — bounded, honest, receipted")
|
|
|
|
| 1273 |
tags=["ayllu"],
|
| 1274 |
summary="Bounded multi-persona deliberation (capped fan-out; optional 2-round debate mode after arXiv:2305.14325)")
|
| 1275 |
app.add_api_route(f"/api/{ns}/v1/ayllu/lounge", _lounge_feed, methods=["GET"],
|
| 1276 |
+
tags=["ayllu"], summary="Opt-in collaboration lounge feed")
|
| 1277 |
app.add_api_route("/ayllu", _page, methods=["GET"], include_in_schema=False)
|
| 1278 |
|
| 1279 |
return (
|
| 1280 |
f"ok — ayllu registered: {len(ROSTER)} personas; live model backend "
|
| 1281 |
f"({_backend.backend_status().get('mode')}); bounded-autonomy Λ-gate; "
|
| 1282 |
+
f"/ayllu + /api/{ns}/v1/ayllu/roster|model-binding|ask|council|lounge; "
|
| 1283 |
f"debate-mode council; council_khipu={council_storage.get('backend')} "
|
| 1284 |
f"(process_restart_durable={council_storage.get('durable')}, "
|
| 1285 |
f"redeploy=NOT_VERIFIED); version={__version__}"
|
|
@@ -57,9 +57,6 @@ import json
|
|
| 57 |
import os
|
| 58 |
import re
|
| 59 |
|
| 60 |
-
from fastapi import FastAPI
|
| 61 |
-
from fastapi.responses import JSONResponse
|
| 62 |
-
|
| 63 |
import a11oy_frontier_page as _frontier
|
| 64 |
import szl_puriq_formulas as _puriq
|
| 65 |
|
|
@@ -555,7 +552,7 @@ def filtered_graph(ns: str = "a11oy", *, layer=None, axis=None, source=None,
|
|
| 555 |
return view
|
| 556 |
|
| 557 |
|
| 558 |
-
def register(app
|
| 559 |
"""Mount GET /api/<ns>/v1/brain/graph. ADDITIVE — before the SPA catch-all.
|
| 560 |
|
| 561 |
Pure read; harvests the real estate + committed field-leader JSONL into a
|
|
@@ -563,6 +560,10 @@ def register(app: FastAPI, ns: str = "a11oy") -> str:
|
|
| 563 |
GET). Query params: ?layer=<int> ?axis=<token> ?source=<token>
|
| 564 |
?kind=<token> ?summary=1 (counts only)."""
|
| 565 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 566 |
@app.get(f"/api/{ns}/v1/brain/graph")
|
| 567 |
async def brain_graph(layer: int = None, axis: str = None,
|
| 568 |
source: str = None, kind: str = None,
|
|
|
|
| 57 |
import os
|
| 58 |
import re
|
| 59 |
|
|
|
|
|
|
|
|
|
|
| 60 |
import a11oy_frontier_page as _frontier
|
| 61 |
import szl_puriq_formulas as _puriq
|
| 62 |
|
|
|
|
| 552 |
return view
|
| 553 |
|
| 554 |
|
| 555 |
+
def register(app, ns: str = "a11oy") -> str:
|
| 556 |
"""Mount GET /api/<ns>/v1/brain/graph. ADDITIVE — before the SPA catch-all.
|
| 557 |
|
| 558 |
Pure read; harvests the real estate + committed field-leader JSONL into a
|
|
|
|
| 560 |
GET). Query params: ?layer=<int> ?axis=<token> ?source=<token>
|
| 561 |
?kind=<token> ?summary=1 (counts only)."""
|
| 562 |
|
| 563 |
+
# Keep the pure graph harvester importable for canonical, offline reindex
|
| 564 |
+
# jobs. Web dependencies are required only when routes are mounted.
|
| 565 |
+
from fastapi.responses import JSONResponse
|
| 566 |
+
|
| 567 |
@app.get(f"/api/{ns}/v1/brain/graph")
|
| 568 |
async def brain_graph(layer: int = None, axis: str = None,
|
| 569 |
source: str = None, kind: str = None,
|
|
@@ -74,7 +74,7 @@ import json
|
|
| 74 |
import math
|
| 75 |
import os
|
| 76 |
import re
|
| 77 |
-
import
|
| 78 |
import subprocess
|
| 79 |
import sys
|
| 80 |
import tempfile
|
|
@@ -83,6 +83,11 @@ from datetime import datetime, timezone
|
|
| 83 |
from pathlib import Path
|
| 84 |
from typing import Any, Optional
|
| 85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
# ---- reuse the PROVEN loop primitives (single source of truth for chain semantics)
|
| 87 |
try:
|
| 88 |
import szl_agentic_loop as _loop
|
|
@@ -344,6 +349,35 @@ _FORBIDDEN_CALLS = ("open(", "eval(", "exec(", "compile(", "__import__", "input(
|
|
| 344 |
"os.remove", "os.rmdir", "os.unlink", "os.environ", "os.popen",
|
| 345 |
"os.fork", "os.kill")
|
| 346 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
|
| 348 |
def _static_screen(code: str) -> dict:
|
| 349 |
"""Static pre-screen BEFORE execution (defense in depth — the loop's policy gate
|
|
@@ -439,6 +473,20 @@ def _sandbox_exec(code: str, lang: str = "python", timeout_s: int = 6,
|
|
| 439 |
"stdout": "", "stderr": "unsupported language: %s" % lang, "exit": -1,
|
| 440 |
"isolation": "n/a"}
|
| 441 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
def _limits():
|
| 443 |
# child-only resource limits (POSIX). Applied in the forked child pre-exec.
|
| 444 |
try:
|
|
@@ -472,8 +520,29 @@ def _sandbox_exec(code: str, lang: str = "python", timeout_s: int = 6,
|
|
| 472 |
)
|
| 473 |
src.write_text(preamble + (code or ""))
|
| 474 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
proc = subprocess.run(
|
| 476 |
-
[sys.executable, "-I", "-S", str(src)],
|
| 477 |
cwd=box, env=env, capture_output=True, text=True,
|
| 478 |
timeout=timeout_s + 1, preexec_fn=_limits,
|
| 479 |
)
|
|
@@ -483,7 +552,7 @@ def _sandbox_exec(code: str, lang: str = "python", timeout_s: int = 6,
|
|
| 483 |
return {"ok": proc.returncode == 0, "stdout": out, "stderr": err,
|
| 484 |
"exit": proc.returncode, "elapsed_ms": dt,
|
| 485 |
"isolation": ("sandboxed (restricted subprocess): separate process, "
|
| 486 |
-
"CPU+memory+fsize+nproc rlimits,
|
| 487 |
"wall-clock timeout, minimal env. Full seccomp/container "
|
| 488 |
"isolation on the tower/UDS pod." % timeout_s)}
|
| 489 |
except subprocess.TimeoutExpired:
|
|
|
|
| 74 |
import math
|
| 75 |
import os
|
| 76 |
import re
|
| 77 |
+
import shutil
|
| 78 |
import subprocess
|
| 79 |
import sys
|
| 80 |
import tempfile
|
|
|
|
| 83 |
from pathlib import Path
|
| 84 |
from typing import Any, Optional
|
| 85 |
|
| 86 |
+
try: # POSIX-only; Windows must import the engine but refuse code execution.
|
| 87 |
+
import resource
|
| 88 |
+
except ImportError: # pragma: no cover - exercised on Windows
|
| 89 |
+
resource = None
|
| 90 |
+
|
| 91 |
# ---- reuse the PROVEN loop primitives (single source of truth for chain semantics)
|
| 92 |
try:
|
| 93 |
import szl_agentic_loop as _loop
|
|
|
|
| 349 |
"os.remove", "os.rmdir", "os.unlink", "os.environ", "os.popen",
|
| 350 |
"os.fork", "os.kill")
|
| 351 |
|
| 352 |
+
_UNSHARE = shutil.which("unshare") if os.name == "posix" else None
|
| 353 |
+
|
| 354 |
+
|
| 355 |
+
def sandbox_capability() -> dict:
|
| 356 |
+
"""Describe the fixed isolation prerequisites without attempting execution.
|
| 357 |
+
|
| 358 |
+
Importability is deliberately separate from executability: Windows can serve
|
| 359 |
+
diagnostics and governed planning, but it cannot claim an isolated code engine
|
| 360 |
+
without POSIX rlimits and a real network namespace boundary.
|
| 361 |
+
"""
|
| 362 |
+
missing = []
|
| 363 |
+
if os.name != "posix":
|
| 364 |
+
missing.append("POSIX_HOST")
|
| 365 |
+
if resource is None:
|
| 366 |
+
missing.append("POSIX_RESOURCE_LIMITS")
|
| 367 |
+
if not _UNSHARE:
|
| 368 |
+
missing.append("UNSHARE_NET_NAMESPACE")
|
| 369 |
+
return {
|
| 370 |
+
"state": "READY_TO_PROBE" if not missing else "UNAVAILABLE",
|
| 371 |
+
"missing": missing,
|
| 372 |
+
"resource_limits": resource is not None,
|
| 373 |
+
"network_namespace_command": _UNSHARE,
|
| 374 |
+
"honesty": (
|
| 375 |
+
"Execution still requires a successful per-run unshare --net probe."
|
| 376 |
+
if not missing else
|
| 377 |
+
"Code execution is refused because the fixed isolation prerequisites are absent."
|
| 378 |
+
),
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
|
| 382 |
def _static_screen(code: str) -> dict:
|
| 383 |
"""Static pre-screen BEFORE execution (defense in depth — the loop's policy gate
|
|
|
|
| 473 |
"stdout": "", "stderr": "unsupported language: %s" % lang, "exit": -1,
|
| 474 |
"isolation": "n/a"}
|
| 475 |
|
| 476 |
+
capability = sandbox_capability()
|
| 477 |
+
if capability["state"] != "READY_TO_PROBE":
|
| 478 |
+
return {
|
| 479 |
+
"ok": False,
|
| 480 |
+
"execution_state": "UNAVAILABLE",
|
| 481 |
+
"error": "fixed sandbox isolation prerequisites unavailable",
|
| 482 |
+
"stdout": "",
|
| 483 |
+
"stderr": "missing: %s" % ", ".join(capability["missing"]),
|
| 484 |
+
"exit": -1,
|
| 485 |
+
"elapsed_ms": 0.0,
|
| 486 |
+
"isolation": "UNAVAILABLE — no code executed",
|
| 487 |
+
"capability": capability,
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
def _limits():
|
| 491 |
# child-only resource limits (POSIX). Applied in the forked child pre-exec.
|
| 492 |
try:
|
|
|
|
| 520 |
)
|
| 521 |
src.write_text(preamble + (code or ""))
|
| 522 |
try:
|
| 523 |
+
# A command being present is not evidence that this host permits a
|
| 524 |
+
# network namespace. Prove the exact boundary immediately before
|
| 525 |
+
# the run; fail closed if the kernel denies it.
|
| 526 |
+
probe = subprocess.run(
|
| 527 |
+
[_UNSHARE, "--net", "--", sys.executable, "-I", "-S", "-c",
|
| 528 |
+
"print('SZL_NETNS_READY')"],
|
| 529 |
+
cwd=box, env=env, capture_output=True, text=True, timeout=3,
|
| 530 |
+
preexec_fn=_limits,
|
| 531 |
+
)
|
| 532 |
+
if probe.returncode != 0 or probe.stdout.strip() != "SZL_NETNS_READY":
|
| 533 |
+
return {
|
| 534 |
+
"ok": False,
|
| 535 |
+
"execution_state": "UNAVAILABLE",
|
| 536 |
+
"error": "network namespace probe failed",
|
| 537 |
+
"stdout": "",
|
| 538 |
+
"stderr": (probe.stderr or "unshare --net did not establish isolation")[:4000],
|
| 539 |
+
"exit": probe.returncode,
|
| 540 |
+
"elapsed_ms": round((time.time() - t0) * 1000, 1),
|
| 541 |
+
"isolation": "UNAVAILABLE — no user code executed",
|
| 542 |
+
"capability": capability,
|
| 543 |
+
}
|
| 544 |
proc = subprocess.run(
|
| 545 |
+
[_UNSHARE, "--net", "--", sys.executable, "-I", "-S", str(src)],
|
| 546 |
cwd=box, env=env, capture_output=True, text=True,
|
| 547 |
timeout=timeout_s + 1, preexec_fn=_limits,
|
| 548 |
)
|
|
|
|
| 552 |
return {"ok": proc.returncode == 0, "stdout": out, "stderr": err,
|
| 553 |
"exit": proc.returncode, "elapsed_ms": dt,
|
| 554 |
"isolation": ("sandboxed (restricted subprocess): separate process, "
|
| 555 |
+
"CPU+memory+fsize+nproc rlimits, unshare --net, %ss "
|
| 556 |
"wall-clock timeout, minimal env. Full seccomp/container "
|
| 557 |
"isolation on the tower/UDS pod." % timeout_s)}
|
| 558 |
except subprocess.TimeoutExpired:
|
|
@@ -153,21 +153,21 @@ def _local_endpoint_reachable(base: str, timeout: float = 2.0) -> bool:
|
|
| 153 |
|
| 154 |
HONESTY GATE: setting A11OY_MODEL_BASE_URL is an INTENT, not proof the GPU is
|
| 155 |
actually serving. We only claim sovereign:true when the endpoint's OpenAI-
|
| 156 |
-
compatible /models
|
| 157 |
(e.g. a tailnet endpoint the Space can't reach), we honestly report a router
|
| 158 |
-
fallback instead of a false sovereign banner.
|
| 159 |
-
|
|
|
|
| 160 |
wiring to this endpoint is tracked separately (see #324)."""
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
return False
|
| 171 |
|
| 172 |
|
| 173 |
def _sovereign_inference_state() -> dict:
|
|
@@ -265,6 +265,252 @@ def _map_model_for_local(model: str) -> str:
|
|
| 265 |
return A11OY_LOCAL_MODEL_MAP.get("default", model)
|
| 266 |
|
| 267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
def _serving_base_selftest() -> dict:
|
| 269 |
"""No-live-endpoint self-test for the #324 serving resolver (Zero-Bandaid).
|
| 270 |
|
|
@@ -852,6 +1098,18 @@ def has_inference_credential() -> bool:
|
|
| 852 |
return bool(_resolve_hf_token()) or any(_resolve_provider_keys().values())
|
| 853 |
|
| 854 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 855 |
def honest_stub_text(user_msg: str, decision: dict[str, Any]) -> str:
|
| 856 |
"""Deterministic, CLEARLY-LABELED stub. NEVER a fabricated model answer.
|
| 857 |
|
|
@@ -861,25 +1119,27 @@ def honest_stub_text(user_msg: str, decision: dict[str, Any]) -> str:
|
|
| 861 |
"""
|
| 862 |
snippet = (user_msg or "").strip().replace("\n", " ")[:160]
|
| 863 |
return (
|
| 864 |
-
"**[deterministic stub \u2014
|
| 865 |
"a11oy.code received your request"
|
| 866 |
+ (f" (\u201c{snippet}\u201d)" if snippet else "")
|
| 867 |
+ f" and routed it to tier **{decision.get('tier')}** \u2192 model "
|
| 868 |
f"`{decision.get('model')}` (license {decision.get('license_class')}). "
|
| 869 |
"The PURIQ \u039b-gate, tier selection and the signed Khipu receipt below are "
|
| 870 |
-
"REAL deterministic math. The **model completion itself is unavailable** because
|
| 871 |
-
"
|
|
|
|
| 872 |
"(Zero-Bandaid Law).\n\n"
|
| 873 |
"_To enable live generation, paste a valid token into the Space secret_ `HF_TOKEN` "
|
| 874 |
"_(Settings \u2192 Variables and secrets). Generation then goes live instantly \u2014 no redeploy._"
|
| 875 |
)
|
| 876 |
|
| 877 |
|
| 878 |
-
async def _call_model_stream(client: httpx.AsyncClient, model: str, payload: dict[str, Any]
|
|
|
|
| 879 |
) -> AsyncGenerator[bytes, None]:
|
| 880 |
base, is_local = _serving_base() # #324: serve local when reachable, else router
|
| 881 |
body = dict(payload)
|
| 882 |
-
body["model"] = _map_model_for_local(model) if is_local else model
|
| 883 |
body["stream"] = True
|
| 884 |
async with client.stream("POST", f"{base}/chat/completions",
|
| 885 |
headers=_inference_headers(is_local), json=body, timeout=120.0) as resp:
|
|
@@ -891,10 +1151,11 @@ async def _call_model_stream(client: httpx.AsyncClient, model: str, payload: dic
|
|
| 891 |
yield (line + "\n").encode()
|
| 892 |
|
| 893 |
|
| 894 |
-
async def _call_model(client: httpx.AsyncClient, model: str, payload: dict[str, Any]
|
|
|
|
| 895 |
base, is_local = _serving_base() # #324: serve local when reachable, else router
|
| 896 |
body = dict(payload)
|
| 897 |
-
body["model"] = _map_model_for_local(model) if is_local else model
|
| 898 |
body["stream"] = False
|
| 899 |
resp = await client.post(f"{base}/chat/completions",
|
| 900 |
headers=_inference_headers(is_local), json=body, timeout=120.0)
|
|
@@ -906,19 +1167,21 @@ async def _call_model(client: httpx.AsyncClient, model: str, payload: dict[str,
|
|
| 906 |
async def agent_model_complete(messages: list[dict], **kw) -> dict[str, Any]:
|
| 907 |
"""model_complete callable injected into the agent loop's FINALIZE step.
|
| 908 |
|
| 909 |
-
If a
|
| 910 |
-
fallback walk). Otherwise returns the
|
| 911 |
-
the agentic control-flow already ran
|
| 912 |
-
|
|
|
|
| 913 |
last = next((m.get("content") for m in reversed(messages)
|
| 914 |
if m.get("role") == "user"), "")
|
| 915 |
snippet = (last if isinstance(last, str) else json.dumps(last)).strip()[:160]
|
| 916 |
stub_text = (
|
| 917 |
-
"**[deterministic stub —
|
| 918 |
"The a11oy Code agent's governed control-flow (plan DAG, per-step Λ-gate, "
|
| 919 |
"PURIQ gate, typed evidence, signed Khipu receipts) executed FOR REAL. The "
|
| 920 |
-
"model-authored synthesis is unavailable because
|
| 921 |
-
f"
|
|
|
|
| 922 |
"is fabricated (Zero-Bandaid Law)."
|
| 923 |
+ (f" Request: \u201c{snippet}\u201d." if snippet else ""))
|
| 924 |
out = {"text": stub_text, "model": "deterministic-stub", "stub": True}
|
|
@@ -932,17 +1195,67 @@ async def agent_model_complete(messages: list[dict], **kw) -> dict[str, Any]:
|
|
| 932 |
"temperature": kw.get("temperature", 0.4)}
|
| 933 |
candidates = [decision["model"], *decision.get("fallbacks", [])]
|
| 934 |
_, is_local = _serving_base() # honest sovereign posture for the receipt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 935 |
try:
|
| 936 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 937 |
text = (data.get("choices", [{}])[0].get("message", {}) or {}).get("content", "") or ""
|
| 938 |
-
out = {"text": text, "model": model_used, "stub": False
|
|
|
|
|
|
|
|
|
|
| 939 |
rcpt = _emit_turn_receipt(text, model_used, is_local, False)
|
| 940 |
if rcpt is not None:
|
| 941 |
out["energy_receipt"] = rcpt
|
| 942 |
return out
|
| 943 |
except Exception as exc:
|
| 944 |
err_text = f"[honest error: live model call failed: {str(exc)[:200]}]"
|
| 945 |
-
out = {"text": err_text, "model": "error", "stub": True
|
|
|
|
| 946 |
rcpt = _emit_turn_receipt(err_text, "error", is_local, True)
|
| 947 |
if rcpt is not None:
|
| 948 |
out["energy_receipt"] = rcpt
|
|
@@ -1075,8 +1388,120 @@ def _agent_rag_query(q: str, **kw) -> dict[str, Any]:
|
|
| 1075 |
return _orgrag.query(q, k=kw.get("k", 6), emit_receipt=khipu_emit)
|
| 1076 |
|
| 1077 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1078 |
async def _call_model_resilient(
|
| 1079 |
-
client: httpx.AsyncClient, models: list[str], payload: dict[str, Any]
|
|
|
|
| 1080 |
) -> tuple[dict[str, Any], str]:
|
| 1081 |
"""Bounded fallback walk over [primary, *fallbacks]. Returns (response, model_used).
|
| 1082 |
On rate-limit / unavailable-model / provider errors it advances to the next
|
|
@@ -1089,8 +1514,17 @@ async def _call_model_resilient(
|
|
| 1089 |
continue
|
| 1090 |
seen.add(m)
|
| 1091 |
try:
|
| 1092 |
-
|
| 1093 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1094 |
except Exception as exc: # provider 4xx/5xx, timeout, etc.
|
| 1095 |
last_exc = exc
|
| 1096 |
_METRICS["router_fallbacks_total"] = _METRICS.get("router_fallbacks_total", 0) + 1
|
|
@@ -1911,7 +2345,7 @@ async def agent_status() -> JSONResponse:
|
|
| 1911 |
"guards": {"max_steps": _agent.MAX_STEPS,
|
| 1912 |
"max_reflect_depth": _agent.MAX_REFLECT_DEPTH,
|
| 1913 |
"lambda_floor": _agent.LAMBDA_FLOOR},
|
| 1914 |
-
"mode": "live" if
|
| 1915 |
"token_secret": _code_secret_name(),
|
| 1916 |
"recent_reflections": _agent.recent_reflections(limit=10),
|
| 1917 |
})
|
|
@@ -2384,13 +2818,14 @@ async def chat_stream(request: Request):
|
|
| 2384 |
return
|
| 2385 |
|
| 2386 |
# ----------------------------------------------------------------
|
| 2387 |
-
# HONEST-STUB BRANCH: if there is
|
|
|
|
| 2388 |
# error out and do NOT fabricate. Stream a clearly-labeled stub plus
|
| 2389 |
# the real signed receipt, then finish cleanly. This keeps the tab
|
| 2390 |
# fully operational (routing + Lambda + receipt) while being honest
|
| 2391 |
-
# that the model text is unavailable until a
|
| 2392 |
# ----------------------------------------------------------------
|
| 2393 |
-
if not
|
| 2394 |
stub = honest_stub_text(user_msg, decision)
|
| 2395 |
for word in re.findall(r"\S+\s*", stub):
|
| 2396 |
yield sse("token", {"text": word})
|
|
|
|
| 153 |
|
| 154 |
HONESTY GATE: setting A11OY_MODEL_BASE_URL is an INTENT, not proof the GPU is
|
| 155 |
actually serving. We only claim sovereign:true when the endpoint's OpenAI-
|
| 156 |
+
compatible /models actually returns bounded JSON. If it's set but unreachable
|
| 157 |
(e.g. a tailnet endpoint the Space can't reach), we honestly report a router
|
| 158 |
+
fallback instead of a false sovereign banner. The probe uses the same pinned,
|
| 159 |
+
redirect-revalidating SSRF guard as model identity reads. NOTE: this reflects
|
| 160 |
+
ENDPOINT liveness; the chat-serving path
|
| 161 |
wiring to this endpoint is tracked separately (see #324)."""
|
| 162 |
+
try:
|
| 163 |
+
payload = _endpoint_json(
|
| 164 |
+
base.rstrip("/") + "/models",
|
| 165 |
+
timeout=timeout,
|
| 166 |
+
allow_private=True,
|
| 167 |
+
)
|
| 168 |
+
return isinstance(payload, dict)
|
| 169 |
+
except Exception: # noqa: BLE001 - any failure => not reachable, stay honest
|
| 170 |
+
return False
|
|
|
|
| 171 |
|
| 172 |
|
| 173 |
def _sovereign_inference_state() -> dict:
|
|
|
|
| 265 |
return A11OY_LOCAL_MODEL_MAP.get("default", model)
|
| 266 |
|
| 267 |
|
| 268 |
+
# Forge profiles are runtime intents, not claims that five separately-trained
|
| 269 |
+
# adapters exist. Two exact tags are real on the current sovereign runtime
|
| 270 |
+
# (ReceiptAgent and Khipu); the remaining roles intentionally share szl1 until
|
| 271 |
+
# separately-qualified weights and receipts exist. Read overrides at call time
|
| 272 |
+
# so an operator can change a loaded tag without rebuilding the service.
|
| 273 |
+
_FORGE_PROFILE_DEFAULTS = {
|
| 274 |
+
"ReceiptAgent-v1": "receiptagent:latest",
|
| 275 |
+
"BrainNavigator-v1": "khipu:latest",
|
| 276 |
+
"Operator-v1": "szl1:latest",
|
| 277 |
+
"Sentinel-v1": "szl1:latest",
|
| 278 |
+
"Anatomy-v1": "szl1:latest",
|
| 279 |
+
}
|
| 280 |
+
_FORGE_PROFILE_ENV = {
|
| 281 |
+
"ReceiptAgent-v1": "A11OY_FORGE_RECEIPT_MODEL",
|
| 282 |
+
"BrainNavigator-v1": "A11OY_FORGE_BRAIN_MODEL",
|
| 283 |
+
"Operator-v1": "A11OY_FORGE_OPERATOR_MODEL",
|
| 284 |
+
"Sentinel-v1": "A11OY_FORGE_SENTINEL_MODEL",
|
| 285 |
+
"Anatomy-v1": "A11OY_FORGE_ANATOMY_MODEL",
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
def forge_profile_model_map() -> dict[str, str]:
|
| 290 |
+
"""Return the exact local tag intended for every governed Forge profile.
|
| 291 |
+
|
| 292 |
+
``A11OY_FORGE_PROFILE_MODELS_JSON`` is an additive whole-map override. Bad
|
| 293 |
+
JSON or unknown keys are ignored rather than weakening the profile boundary.
|
| 294 |
+
"""
|
| 295 |
+
out = {
|
| 296 |
+
profile: (os.environ.get(_FORGE_PROFILE_ENV[profile]) or default).strip()
|
| 297 |
+
for profile, default in _FORGE_PROFILE_DEFAULTS.items()
|
| 298 |
+
}
|
| 299 |
+
try:
|
| 300 |
+
raw = os.environ.get("A11OY_FORGE_PROFILE_MODELS_JSON", "").strip()
|
| 301 |
+
override = json.loads(raw) if raw else {}
|
| 302 |
+
if isinstance(override, dict):
|
| 303 |
+
for profile, tag in override.items():
|
| 304 |
+
if profile in out and isinstance(tag, str) and tag.strip():
|
| 305 |
+
out[profile] = tag.strip()
|
| 306 |
+
except Exception:
|
| 307 |
+
pass
|
| 308 |
+
return out
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
def _endpoint_json(url: str, *, body: dict[str, Any] | None = None,
|
| 312 |
+
timeout: float = 2.0, allow_private: bool = False) -> dict[str, Any]:
|
| 313 |
+
"""Fetch a bounded provider document through the shared SSRF guard.
|
| 314 |
+
|
| 315 |
+
Private/loopback access is never inferred from the URL. Callers must grant
|
| 316 |
+
it explicitly, and only do so for the operator-configured self-hosted base.
|
| 317 |
+
The shared transport pins validated DNS answers, revalidates every redirect,
|
| 318 |
+
rejects link-local metadata destinations, and enforces request/response caps.
|
| 319 |
+
"""
|
| 320 |
+
try:
|
| 321 |
+
from szl_provider_http import http_json as _provider_http_json
|
| 322 |
+
except Exception as exc: # pragma: no cover - packaged runtime always includes it
|
| 323 |
+
raise RuntimeError("PROVIDER_HTTP_UNAVAILABLE") from exc
|
| 324 |
+
|
| 325 |
+
encoded = (None if body is None else json.dumps(
|
| 326 |
+
body, sort_keys=True, separators=(",", ":"), ensure_ascii=False
|
| 327 |
+
).encode("utf-8"))
|
| 328 |
+
parsed, error = _provider_http_json(
|
| 329 |
+
url,
|
| 330 |
+
method="POST" if encoded is not None else "GET",
|
| 331 |
+
body=encoded,
|
| 332 |
+
timeout=timeout,
|
| 333 |
+
max_response_bytes=4 * 1024 * 1024,
|
| 334 |
+
max_redirects=2,
|
| 335 |
+
allow_private=allow_private,
|
| 336 |
+
)
|
| 337 |
+
if error:
|
| 338 |
+
raise RuntimeError(f"PROVIDER_HTTP:{error}")
|
| 339 |
+
return parsed if isinstance(parsed, dict) else {}
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
def _served_model_ids(base: str, timeout: float = 2.0) -> list[str]:
|
| 343 |
+
try:
|
| 344 |
+
payload = _endpoint_json(
|
| 345 |
+
base.rstrip("/") + "/models", timeout=timeout, allow_private=True)
|
| 346 |
+
except Exception:
|
| 347 |
+
return []
|
| 348 |
+
rows = payload.get("data") or payload.get("models") or []
|
| 349 |
+
out: list[str] = []
|
| 350 |
+
if isinstance(rows, list):
|
| 351 |
+
for row in rows:
|
| 352 |
+
value = row.get("id") if isinstance(row, dict) else row
|
| 353 |
+
if isinstance(value, str) and value.strip():
|
| 354 |
+
out.append(value.strip())
|
| 355 |
+
return sorted(set(out), key=str.lower)
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
def _model_origin(base: str) -> str:
|
| 359 |
+
from urllib.parse import urlsplit as _split, urlunsplit as _unsplit
|
| 360 |
+
|
| 361 |
+
parts = _split(base)
|
| 362 |
+
return _unsplit((parts.scheme, parts.netloc, "", "", "")).rstrip("/")
|
| 363 |
+
|
| 364 |
+
|
| 365 |
+
def attest_local_model(profile_id: str, *, timeout: float = 2.0) -> dict[str, Any]:
|
| 366 |
+
"""Attest one exact served tag without equating endpoint liveness to model load.
|
| 367 |
+
|
| 368 |
+
A matching OpenAI ``/models`` identity is mandatory. When the endpoint is
|
| 369 |
+
Ollama-compatible, ``/api/show`` additionally binds family, quantization,
|
| 370 |
+
template, parameters, and the local GGUF blob digest. A live tag is still
|
| 371 |
+
``ARTIFACT_UNBOUND`` until a release manifest supplies and matches an expected
|
| 372 |
+
immutable blob digest; this deliberately prevents a same-name model swap.
|
| 373 |
+
"""
|
| 374 |
+
models = forge_profile_model_map()
|
| 375 |
+
expected = models.get(profile_id)
|
| 376 |
+
base, is_local = _serving_base()
|
| 377 |
+
result: dict[str, Any] = {
|
| 378 |
+
"schema": "szl.forge.local-model-attestation/v1",
|
| 379 |
+
"profile_id": profile_id,
|
| 380 |
+
"expected_model": expected,
|
| 381 |
+
"base_url": base,
|
| 382 |
+
"local_endpoint": bool(is_local),
|
| 383 |
+
"observed_at_unix": int(time.time()),
|
| 384 |
+
"artifact_binding": "UNBOUND",
|
| 385 |
+
}
|
| 386 |
+
if not expected:
|
| 387 |
+
result.update({"state": "UNKNOWN_PROFILE", "available": False})
|
| 388 |
+
return result
|
| 389 |
+
if not is_local:
|
| 390 |
+
result.update({"state": "LOCAL_ENDPOINT_UNAVAILABLE", "available": False})
|
| 391 |
+
return result
|
| 392 |
+
served = _served_model_ids(base, timeout=timeout)
|
| 393 |
+
# Model identifiers are cryptographic identity inputs, not display labels.
|
| 394 |
+
# Case-folding here would let a differently named tag impersonate a profile.
|
| 395 |
+
exact = expected if expected in served else None
|
| 396 |
+
result["served_model_count"] = len(served)
|
| 397 |
+
result["served_models_sha256"] = hashlib.sha256(
|
| 398 |
+
json.dumps(served, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
|
| 399 |
+
).hexdigest()
|
| 400 |
+
if exact is None:
|
| 401 |
+
result.update({
|
| 402 |
+
"state": "MODEL_TAG_MISSING",
|
| 403 |
+
"available": False,
|
| 404 |
+
"honesty": "endpoint is live but the exact profile tag is absent",
|
| 405 |
+
})
|
| 406 |
+
return result
|
| 407 |
+
|
| 408 |
+
result.update({
|
| 409 |
+
"state": "TAG_ATTESTED_ARTIFACT_UNBOUND",
|
| 410 |
+
"available": True,
|
| 411 |
+
"served_model": exact,
|
| 412 |
+
})
|
| 413 |
+
try:
|
| 414 |
+
show = _endpoint_json(
|
| 415 |
+
_model_origin(base) + "/api/show", body={"model": exact},
|
| 416 |
+
timeout=timeout, allow_private=True)
|
| 417 |
+
details = show.get("details") if isinstance(show.get("details"), dict) else {}
|
| 418 |
+
modelfile = str(show.get("modelfile") or "")
|
| 419 |
+
layer_digests = sorted(set(
|
| 420 |
+
value.lower() for value in re.findall(
|
| 421 |
+
r"sha256[:-]([0-9a-fA-F]{64})(?![0-9a-fA-F])", modelfile)
|
| 422 |
+
))
|
| 423 |
+
result["runtime"] = "ollama"
|
| 424 |
+
result["model_details"] = {
|
| 425 |
+
"format": details.get("format"),
|
| 426 |
+
"family": details.get("family"),
|
| 427 |
+
"parameter_size": details.get("parameter_size"),
|
| 428 |
+
"quantization_level": details.get("quantization_level"),
|
| 429 |
+
}
|
| 430 |
+
result["model_manifest_sha256"] = hashlib.sha256(json.dumps(
|
| 431 |
+
show, sort_keys=True, separators=(",", ":"), ensure_ascii=False
|
| 432 |
+
).encode("utf-8")).hexdigest()
|
| 433 |
+
result["modelfile_sha256"] = hashlib.sha256(
|
| 434 |
+
modelfile.encode("utf-8")).hexdigest()
|
| 435 |
+
result["modelfile_layer_sha256"] = layer_digests
|
| 436 |
+
# Compatibility field remains singular only when the manifest really
|
| 437 |
+
# contains one layer. Multiple layers must never be collapsed to the
|
| 438 |
+
# first regex match.
|
| 439 |
+
result["weights_blob_sha256"] = (
|
| 440 |
+
layer_digests[0] if len(layer_digests) == 1 else None)
|
| 441 |
+
for field in ("details", "model_info", "capabilities", "license"):
|
| 442 |
+
if field in show:
|
| 443 |
+
result[field + "_sha256"] = hashlib.sha256(json.dumps(
|
| 444 |
+
show.get(field), sort_keys=True, separators=(",", ":"),
|
| 445 |
+
ensure_ascii=False
|
| 446 |
+
).encode("utf-8")).hexdigest()
|
| 447 |
+
for field in ("template", "parameters", "system"):
|
| 448 |
+
value = str(show.get(field) or "")
|
| 449 |
+
result[field + "_sha256"] = hashlib.sha256(value.encode("utf-8")).hexdigest()
|
| 450 |
+
try:
|
| 451 |
+
tags = _endpoint_json(
|
| 452 |
+
_model_origin(base) + "/api/tags", timeout=timeout,
|
| 453 |
+
allow_private=True)
|
| 454 |
+
rows = tags.get("models") if isinstance(tags.get("models"), list) else []
|
| 455 |
+
tag_row = next((row for row in rows if isinstance(row, dict) and (
|
| 456 |
+
row.get("name") == exact or row.get("model") == exact)), None)
|
| 457 |
+
if tag_row is not None:
|
| 458 |
+
result["tag_manifest_sha256"] = hashlib.sha256(json.dumps(
|
| 459 |
+
tag_row, sort_keys=True, separators=(",", ":"),
|
| 460 |
+
ensure_ascii=False
|
| 461 |
+
).encode("utf-8")).hexdigest()
|
| 462 |
+
runtime_digest = tag_row.get("digest")
|
| 463 |
+
result["runtime_model_digest"] = (
|
| 464 |
+
runtime_digest.lower()
|
| 465 |
+
if isinstance(runtime_digest, str)
|
| 466 |
+
and re.fullmatch(r"[0-9a-fA-F]{64}", runtime_digest)
|
| 467 |
+
else None
|
| 468 |
+
)
|
| 469 |
+
else:
|
| 470 |
+
result["tag_manifest_state"] = "EXACT_TAG_NOT_IN_OLLAMA_TAGS"
|
| 471 |
+
except Exception as exc:
|
| 472 |
+
result["tag_manifest_state"] = "UNAVAILABLE"
|
| 473 |
+
result["tag_manifest_error_type"] = type(exc).__name__
|
| 474 |
+
except Exception as exc:
|
| 475 |
+
result["runtime"] = "openai-compatible"
|
| 476 |
+
result["show_state"] = "UNAVAILABLE"
|
| 477 |
+
result["show_error_type"] = type(exc).__name__
|
| 478 |
+
result["attestation_sha256"] = hashlib.sha256(
|
| 479 |
+
json.dumps(result, sort_keys=True, separators=(",", ":"),
|
| 480 |
+
ensure_ascii=False).encode("utf-8")
|
| 481 |
+
).hexdigest()
|
| 482 |
+
return result
|
| 483 |
+
|
| 484 |
+
|
| 485 |
+
def forge_profile_runtime_status() -> dict[str, Any]:
|
| 486 |
+
"""Shallow exact-tag inventory for status/UI surfaces (one /models read)."""
|
| 487 |
+
base, is_local = _serving_base()
|
| 488 |
+
served = _served_model_ids(base) if is_local else []
|
| 489 |
+
exact_served = set(served)
|
| 490 |
+
profiles = {}
|
| 491 |
+
for profile, tag in forge_profile_model_map().items():
|
| 492 |
+
actual = tag if tag in exact_served else None
|
| 493 |
+
profiles[profile] = {
|
| 494 |
+
"expected_model": tag,
|
| 495 |
+
"available": actual is not None,
|
| 496 |
+
"served_model": actual,
|
| 497 |
+
"state": ("EXACT_TAG_OBSERVED_ARTIFACT_UNBOUND" if actual is not None
|
| 498 |
+
else "MODEL_TAG_MISSING" if is_local
|
| 499 |
+
else "LOCAL_ENDPOINT_UNAVAILABLE"),
|
| 500 |
+
"separate_profile_weights_claimed": profile in {
|
| 501 |
+
"ReceiptAgent-v1", "BrainNavigator-v1"},
|
| 502 |
+
}
|
| 503 |
+
return {
|
| 504 |
+
"schema": "szl.forge.profile-runtime-status/v1",
|
| 505 |
+
"local_endpoint": bool(is_local),
|
| 506 |
+
"base_url": base,
|
| 507 |
+
"served_model_count": len(served),
|
| 508 |
+
"profiles": profiles,
|
| 509 |
+
"honesty": ("exact tag observation is not release-artifact identity; turn-level "
|
| 510 |
+
"attestation remains authoritative"),
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
|
| 514 |
def _serving_base_selftest() -> dict:
|
| 515 |
"""No-live-endpoint self-test for the #324 serving resolver (Zero-Bandaid).
|
| 516 |
|
|
|
|
| 1098 |
return bool(_resolve_hf_token()) or any(_resolve_provider_keys().values())
|
| 1099 |
|
| 1100 |
|
| 1101 |
+
def inference_backend_ready() -> bool:
|
| 1102 |
+
"""True when either a reachable local backend or remote credential is usable.
|
| 1103 |
+
|
| 1104 |
+
A local Ollama/LM Studio-style endpoint may intentionally require no API key.
|
| 1105 |
+
This is distinct from :func:`has_inference_credential`: it never relabels a
|
| 1106 |
+
no-key local service as credentialed, and an unreachable local URL does not
|
| 1107 |
+
make the remote fallback live without a real remote credential.
|
| 1108 |
+
"""
|
| 1109 |
+
_base, is_local = _serving_base()
|
| 1110 |
+
return bool(is_local or has_inference_credential())
|
| 1111 |
+
|
| 1112 |
+
|
| 1113 |
def honest_stub_text(user_msg: str, decision: dict[str, Any]) -> str:
|
| 1114 |
"""Deterministic, CLEARLY-LABELED stub. NEVER a fabricated model answer.
|
| 1115 |
|
|
|
|
| 1119 |
"""
|
| 1120 |
snippet = (user_msg or "").strip().replace("\n", " ")[:160]
|
| 1121 |
return (
|
| 1122 |
+
"**[deterministic stub \u2014 no usable inference backend]**\n\n"
|
| 1123 |
"a11oy.code received your request"
|
| 1124 |
+ (f" (\u201c{snippet}\u201d)" if snippet else "")
|
| 1125 |
+ f" and routed it to tier **{decision.get('tier')}** \u2192 model "
|
| 1126 |
f"`{decision.get('model')}` (license {decision.get('license_class')}). "
|
| 1127 |
"The PURIQ \u039b-gate, tier selection and the signed Khipu receipt below are "
|
| 1128 |
+
"REAL deterministic math. The **model completion itself is unavailable** because "
|
| 1129 |
+
"neither a reachable local endpoint nor a credentialed remote provider is available "
|
| 1130 |
+
"\u2014 so no answer is fabricated "
|
| 1131 |
"(Zero-Bandaid Law).\n\n"
|
| 1132 |
"_To enable live generation, paste a valid token into the Space secret_ `HF_TOKEN` "
|
| 1133 |
"_(Settings \u2192 Variables and secrets). Generation then goes live instantly \u2014 no redeploy._"
|
| 1134 |
)
|
| 1135 |
|
| 1136 |
|
| 1137 |
+
async def _call_model_stream(client: httpx.AsyncClient, model: str, payload: dict[str, Any],
|
| 1138 |
+
*, local_model: str | None = None
|
| 1139 |
) -> AsyncGenerator[bytes, None]:
|
| 1140 |
base, is_local = _serving_base() # #324: serve local when reachable, else router
|
| 1141 |
body = dict(payload)
|
| 1142 |
+
body["model"] = (local_model or _map_model_for_local(model)) if is_local else model
|
| 1143 |
body["stream"] = True
|
| 1144 |
async with client.stream("POST", f"{base}/chat/completions",
|
| 1145 |
headers=_inference_headers(is_local), json=body, timeout=120.0) as resp:
|
|
|
|
| 1151 |
yield (line + "\n").encode()
|
| 1152 |
|
| 1153 |
|
| 1154 |
+
async def _call_model(client: httpx.AsyncClient, model: str, payload: dict[str, Any],
|
| 1155 |
+
*, local_model: str | None = None) -> dict[str, Any]:
|
| 1156 |
base, is_local = _serving_base() # #324: serve local when reachable, else router
|
| 1157 |
body = dict(payload)
|
| 1158 |
+
body["model"] = (local_model or _map_model_for_local(model)) if is_local else model
|
| 1159 |
body["stream"] = False
|
| 1160 |
resp = await client.post(f"{base}/chat/completions",
|
| 1161 |
headers=_inference_headers(is_local), json=body, timeout=120.0)
|
|
|
|
| 1167 |
async def agent_model_complete(messages: list[dict], **kw) -> dict[str, Any]:
|
| 1168 |
"""model_complete callable injected into the agent loop's FINALIZE step.
|
| 1169 |
|
| 1170 |
+
If a reachable local endpoint or credentialed remote provider is available,
|
| 1171 |
+
calls the live model (resilient fallback walk). Otherwise returns the
|
| 1172 |
+
CLEARLY-LABELED deterministic stub — the agentic control-flow already ran
|
| 1173 |
+
for real (Zero-Bandaid Law)."""
|
| 1174 |
+
if not inference_backend_ready():
|
| 1175 |
last = next((m.get("content") for m in reversed(messages)
|
| 1176 |
if m.get("role") == "user"), "")
|
| 1177 |
snippet = (last if isinstance(last, str) else json.dumps(last)).strip()[:160]
|
| 1178 |
stub_text = (
|
| 1179 |
+
"**[deterministic stub — no usable inference backend]**\n\n"
|
| 1180 |
"The a11oy Code agent's governed control-flow (plan DAG, per-step Λ-gate, "
|
| 1181 |
"PURIQ gate, typed evidence, signed Khipu receipts) executed FOR REAL. The "
|
| 1182 |
+
"model-authored synthesis is unavailable because neither a reachable local "
|
| 1183 |
+
f"endpoint nor a credentialed remote provider (secret {_code_secret_name()}) "
|
| 1184 |
+
"is available, so no answer "
|
| 1185 |
"is fabricated (Zero-Bandaid Law)."
|
| 1186 |
+ (f" Request: \u201c{snippet}\u201d." if snippet else ""))
|
| 1187 |
out = {"text": stub_text, "model": "deterministic-stub", "stub": True}
|
|
|
|
| 1195 |
"temperature": kw.get("temperature", 0.4)}
|
| 1196 |
candidates = [decision["model"], *decision.get("fallbacks", [])]
|
| 1197 |
_, is_local = _serving_base() # honest sovereign posture for the receipt
|
| 1198 |
+
local_profile = kw.get("local_profile")
|
| 1199 |
+
local_model = None
|
| 1200 |
+
model_attestation = None
|
| 1201 |
+
if is_local and isinstance(local_profile, str) and local_profile:
|
| 1202 |
+
local_model = forge_profile_model_map().get(local_profile)
|
| 1203 |
+
model_attestation = attest_local_model(local_profile)
|
| 1204 |
+
if not model_attestation.get("available"):
|
| 1205 |
+
honesty = (
|
| 1206 |
+
"exact Forge profile model is not loaded; refusing to relabel or use a "
|
| 1207 |
+
"different local model"
|
| 1208 |
+
)
|
| 1209 |
+
out = {
|
| 1210 |
+
"text": None,
|
| 1211 |
+
"model": local_model or "unavailable",
|
| 1212 |
+
"stub": True,
|
| 1213 |
+
"honesty": honesty,
|
| 1214 |
+
"model_attestation": model_attestation,
|
| 1215 |
+
}
|
| 1216 |
+
rcpt = _emit_turn_receipt(honesty, out["model"], True, True)
|
| 1217 |
+
if rcpt is not None:
|
| 1218 |
+
out["energy_receipt"] = rcpt
|
| 1219 |
+
return out
|
| 1220 |
try:
|
| 1221 |
+
if local_model:
|
| 1222 |
+
data, model_used = await _call_model_resilient(
|
| 1223 |
+
client, candidates, payload, local_model=local_model)
|
| 1224 |
+
else:
|
| 1225 |
+
data, model_used = await _call_model_resilient(client, candidates, payload)
|
| 1226 |
+
if local_model and model_attestation is not None:
|
| 1227 |
+
attested_tag = model_attestation.get("served_model")
|
| 1228 |
+
if model_used != attested_tag:
|
| 1229 |
+
honesty = (
|
| 1230 |
+
"model response identity did not exactly match the case-sensitive "
|
| 1231 |
+
"attested served tag; refusing the response"
|
| 1232 |
+
)
|
| 1233 |
+
out = {
|
| 1234 |
+
"text": None,
|
| 1235 |
+
"model": model_used,
|
| 1236 |
+
"stub": True,
|
| 1237 |
+
"honesty": honesty,
|
| 1238 |
+
"model_identity_state": "RESPONSE_TAG_MISMATCH",
|
| 1239 |
+
"attested_served_model": attested_tag,
|
| 1240 |
+
"model_attestation": model_attestation,
|
| 1241 |
+
}
|
| 1242 |
+
rcpt = _emit_turn_receipt(honesty, model_used, is_local, True)
|
| 1243 |
+
if rcpt is not None:
|
| 1244 |
+
out["energy_receipt"] = rcpt
|
| 1245 |
+
return out
|
| 1246 |
text = (data.get("choices", [{}])[0].get("message", {}) or {}).get("content", "") or ""
|
| 1247 |
+
out = {"text": text, "model": model_used, "stub": False,
|
| 1248 |
+
"model_attestation": model_attestation,
|
| 1249 |
+
"model_identity_state": (
|
| 1250 |
+
"EXACT_ATTESTED_TAG" if local_model else "PROVIDER_REPORTED")}
|
| 1251 |
rcpt = _emit_turn_receipt(text, model_used, is_local, False)
|
| 1252 |
if rcpt is not None:
|
| 1253 |
out["energy_receipt"] = rcpt
|
| 1254 |
return out
|
| 1255 |
except Exception as exc:
|
| 1256 |
err_text = f"[honest error: live model call failed: {str(exc)[:200]}]"
|
| 1257 |
+
out = {"text": err_text, "model": "error", "stub": True,
|
| 1258 |
+
"model_attestation": model_attestation}
|
| 1259 |
rcpt = _emit_turn_receipt(err_text, "error", is_local, True)
|
| 1260 |
if rcpt is not None:
|
| 1261 |
out["energy_receipt"] = rcpt
|
|
|
|
| 1388 |
return _orgrag.query(q, k=kw.get("k", 6), emit_receipt=khipu_emit)
|
| 1389 |
|
| 1390 |
|
| 1391 |
+
def agent_rag_context(q: str, *, k: int = 6) -> dict[str, Any]:
|
| 1392 |
+
"""Return evidence-bound Brain handles for a governed navigator model.
|
| 1393 |
+
|
| 1394 |
+
Node content remains in the controller. The model receives only handles and
|
| 1395 |
+
synthetic metadata, matching the Khipu model contract. The API response can
|
| 1396 |
+
independently resolve each selected handle against the evidence-set digest.
|
| 1397 |
+
"""
|
| 1398 |
+
raw = _agent_rag_query(q, k=max(1, min(int(k), 12)))
|
| 1399 |
+
chunks = raw.get("chunks") if isinstance(raw, dict) else []
|
| 1400 |
+
chunks = chunks if isinstance(chunks, list) else []
|
| 1401 |
+
handles: list[dict[str, Any]] = []
|
| 1402 |
+
evidence: list[dict[str, Any]] = []
|
| 1403 |
+
for chunk in chunks:
|
| 1404 |
+
if not isinstance(chunk, dict):
|
| 1405 |
+
continue
|
| 1406 |
+
ev = chunk.get("evidence") if isinstance(chunk.get("evidence"), dict) else {}
|
| 1407 |
+
handle = {
|
| 1408 |
+
"nodeId": chunk.get("node_id"),
|
| 1409 |
+
"chunkId": chunk.get("chunk_id"),
|
| 1410 |
+
"title": chunk.get("title"),
|
| 1411 |
+
"repo": chunk.get("repo"),
|
| 1412 |
+
"path": chunk.get("path"),
|
| 1413 |
+
"corpus": chunk.get("corpus"),
|
| 1414 |
+
"lambda": chunk.get("lambda"),
|
| 1415 |
+
"scores": chunk.get("scores"),
|
| 1416 |
+
"sha256": chunk.get("sha256"),
|
| 1417 |
+
}
|
| 1418 |
+
handles.append(handle)
|
| 1419 |
+
evidence.append({
|
| 1420 |
+
"node_id": chunk.get("node_id"),
|
| 1421 |
+
"chunk_id": chunk.get("chunk_id"),
|
| 1422 |
+
"sha256": chunk.get("sha256"),
|
| 1423 |
+
"path": ev.get("path") or chunk.get("path"),
|
| 1424 |
+
"source": ev.get("source") or chunk.get("source"),
|
| 1425 |
+
"citation": ev.get("citation"),
|
| 1426 |
+
})
|
| 1427 |
+
evidence_set = raw.get("evidence_set") if isinstance(raw, dict) else None
|
| 1428 |
+
if not isinstance(evidence_set, list):
|
| 1429 |
+
evidence_set = evidence
|
| 1430 |
+
|
| 1431 |
+
def _membership_row(row: Any, *, handle: bool) -> tuple[Any, Any, Any] | None:
|
| 1432 |
+
if not isinstance(row, dict):
|
| 1433 |
+
return None
|
| 1434 |
+
node_id = row.get("nodeId") if handle else row.get("node_id")
|
| 1435 |
+
chunk_id = row.get("chunkId") if handle else row.get("chunk_id")
|
| 1436 |
+
digest = row.get("sha256")
|
| 1437 |
+
if not all(isinstance(value, str) and value for value in (
|
| 1438 |
+
node_id, chunk_id, digest)):
|
| 1439 |
+
return None
|
| 1440 |
+
if re.fullmatch(r"[0-9a-f]{64}", digest) is None:
|
| 1441 |
+
return None
|
| 1442 |
+
return node_id, chunk_id, digest
|
| 1443 |
+
|
| 1444 |
+
handle_members = [_membership_row(row, handle=True) for row in handles]
|
| 1445 |
+
evidence_members = [_membership_row(row, handle=False) for row in evidence_set]
|
| 1446 |
+
membership_rows_valid = (
|
| 1447 |
+
all(row is not None for row in handle_members)
|
| 1448 |
+
and all(row is not None for row in evidence_members)
|
| 1449 |
+
)
|
| 1450 |
+
handle_member_set = {row for row in handle_members if row is not None}
|
| 1451 |
+
evidence_member_set = {row for row in evidence_members if row is not None}
|
| 1452 |
+
handle_evidence_set_equivalent = (
|
| 1453 |
+
membership_rows_valid
|
| 1454 |
+
and len(handle_members) == len(handle_member_set)
|
| 1455 |
+
and len(evidence_members) == len(evidence_member_set)
|
| 1456 |
+
and handle_member_set == evidence_member_set
|
| 1457 |
+
)
|
| 1458 |
+
computed_evidence_sha = hashlib.sha256(json.dumps(
|
| 1459 |
+
evidence_set, sort_keys=True, separators=(",", ":"), ensure_ascii=False
|
| 1460 |
+
).encode("utf-8")).hexdigest()
|
| 1461 |
+
raw_evidence_sha = raw.get("evidence_set_sha256") if isinstance(raw, dict) else None
|
| 1462 |
+
raw_digest_present = (
|
| 1463 |
+
isinstance(raw_evidence_sha, str)
|
| 1464 |
+
and re.fullmatch(r"[0-9a-f]{64}", raw_evidence_sha) is not None
|
| 1465 |
+
)
|
| 1466 |
+
evidence_digest_matches = (
|
| 1467 |
+
not raw_digest_present or raw_evidence_sha == computed_evidence_sha
|
| 1468 |
+
)
|
| 1469 |
+
evidence_sha = raw_evidence_sha if raw_digest_present else computed_evidence_sha
|
| 1470 |
+
handles_sha = hashlib.sha256(json.dumps(
|
| 1471 |
+
handles, sort_keys=True, separators=(",", ":"), ensure_ascii=False
|
| 1472 |
+
).encode("utf-8")).hexdigest()
|
| 1473 |
+
ready = (bool(raw.get("ok")) and bool(handles)
|
| 1474 |
+
and not bool(raw.get("i_dont_know")) and evidence_digest_matches
|
| 1475 |
+
and handle_evidence_set_equivalent)
|
| 1476 |
+
return {
|
| 1477 |
+
"schema": "szl.brain.navigator-context/v1",
|
| 1478 |
+
"state": (
|
| 1479 |
+
"GROUNDED_HANDLES_READY" if ready
|
| 1480 |
+
else "ABSTAIN_EVIDENCE_DIGEST_CONFLICT" if not evidence_digest_matches
|
| 1481 |
+
else "ABSTAIN_HANDLE_EVIDENCE_SET_MISMATCH"
|
| 1482 |
+
if not handle_evidence_set_equivalent
|
| 1483 |
+
else "ABSTAIN_NO_GROUNDED_HANDLES"
|
| 1484 |
+
),
|
| 1485 |
+
"ready": ready,
|
| 1486 |
+
"content_access": "HANDLES_ONLY",
|
| 1487 |
+
"query_sha256": hashlib.sha256((q or "").encode("utf-8")).hexdigest(),
|
| 1488 |
+
"handles": handles,
|
| 1489 |
+
"evidence": evidence_set,
|
| 1490 |
+
"evidence_set_sha256": evidence_sha,
|
| 1491 |
+
"evidence_digest_matches": evidence_digest_matches,
|
| 1492 |
+
"handle_evidence_set_equivalent": handle_evidence_set_equivalent,
|
| 1493 |
+
"handles_sha256": handles_sha,
|
| 1494 |
+
"grounded_count": len(handles),
|
| 1495 |
+
"lambda_floor": raw.get("lambda_floor"),
|
| 1496 |
+
"dense_used": raw.get("dense_used"),
|
| 1497 |
+
"khipu_hash": raw.get("khipu_hash"),
|
| 1498 |
+
"honesty": raw.get("honest_note") or raw.get("honest_error"),
|
| 1499 |
+
}
|
| 1500 |
+
|
| 1501 |
+
|
| 1502 |
async def _call_model_resilient(
|
| 1503 |
+
client: httpx.AsyncClient, models: list[str], payload: dict[str, Any],
|
| 1504 |
+
*, local_model: str | None = None
|
| 1505 |
) -> tuple[dict[str, Any], str]:
|
| 1506 |
"""Bounded fallback walk over [primary, *fallbacks]. Returns (response, model_used).
|
| 1507 |
On rate-limit / unavailable-model / provider errors it advances to the next
|
|
|
|
| 1514 |
continue
|
| 1515 |
seen.add(m)
|
| 1516 |
try:
|
| 1517 |
+
if local_model:
|
| 1518 |
+
data = await _call_model(client, m, payload, local_model=local_model)
|
| 1519 |
+
else:
|
| 1520 |
+
data = await _call_model(client, m, payload)
|
| 1521 |
+
observed = data.get("model") if isinstance(data, dict) else None
|
| 1522 |
+
if isinstance(observed, str) and observed.strip():
|
| 1523 |
+
model_used = observed.strip()
|
| 1524 |
+
else:
|
| 1525 |
+
_base, is_local = _serving_base()
|
| 1526 |
+
model_used = (local_model or _map_model_for_local(m)) if is_local else m
|
| 1527 |
+
return data, model_used
|
| 1528 |
except Exception as exc: # provider 4xx/5xx, timeout, etc.
|
| 1529 |
last_exc = exc
|
| 1530 |
_METRICS["router_fallbacks_total"] = _METRICS.get("router_fallbacks_total", 0) + 1
|
|
|
|
| 2345 |
"guards": {"max_steps": _agent.MAX_STEPS,
|
| 2346 |
"max_reflect_depth": _agent.MAX_REFLECT_DEPTH,
|
| 2347 |
"lambda_floor": _agent.LAMBDA_FLOOR},
|
| 2348 |
+
"mode": "live" if inference_backend_ready() else "deterministic_stub",
|
| 2349 |
"token_secret": _code_secret_name(),
|
| 2350 |
"recent_reflections": _agent.recent_reflections(limit=10),
|
| 2351 |
})
|
|
|
|
| 2818 |
return
|
| 2819 |
|
| 2820 |
# ----------------------------------------------------------------
|
| 2821 |
+
# HONEST-STUB BRANCH: if there is no reachable local backend and no
|
| 2822 |
+
# credentialed remote backend, do NOT
|
| 2823 |
# error out and do NOT fabricate. Stream a clearly-labeled stub plus
|
| 2824 |
# the real signed receipt, then finish cleanly. This keeps the tab
|
| 2825 |
# fully operational (routing + Lambda + receipt) while being honest
|
| 2826 |
+
# that the model text is unavailable until a backend becomes usable.
|
| 2827 |
# ----------------------------------------------------------------
|
| 2828 |
+
if not inference_backend_ready():
|
| 2829 |
stub = honest_stub_text(user_msg, decision)
|
| 2830 |
for word in re.findall(r"\S+\s*", stub):
|
| 2831 |
yield sse("token", {"text": word})
|
|
@@ -47,9 +47,6 @@ from __future__ import annotations
|
|
| 47 |
import pathlib
|
| 48 |
import re
|
| 49 |
|
| 50 |
-
from fastapi import FastAPI
|
| 51 |
-
from fastapi.responses import HTMLResponse, JSONResponse
|
| 52 |
-
|
| 53 |
DOCTRINE = {"version": "v11", "lambda": "Conjecture 1", "sovereign": False}
|
| 54 |
|
| 55 |
# --------------------------------------------------------------------------- #
|
|
@@ -233,19 +230,23 @@ def _page_html(ns: str) -> str:
|
|
| 233 |
<style>
|
| 234 |
:root {{ --bg:#070b16; --panel:#101a2e; --ink:#e8eef7; --muted:#8aa0bd;
|
| 235 |
--indigo:#4d8fcc; --terra:#c8643c; --gold:#d8a23c; --amber:#e8c074;
|
| 236 |
-
--green:#2fd07a; --warn:#c8893c; --violet:#9d7ad8; --red:#d8624a;
|
|
|
|
| 237 |
* {{ box-sizing:border-box; }}
|
| 238 |
-
html,body {{ margin:0; min-height:100%; }}
|
|
|
|
| 239 |
body {{ font-family:ui-sans-serif,system-ui,Segoe UI,Roboto,sans-serif;
|
| 240 |
-
|
| 241 |
-
|
| 242 |
/* Persistent, unmissable HONEST banner — top of every viewport. */
|
| 243 |
#honest-banner {{ position:fixed; top:0; left:0; right:0; z-index:50;
|
| 244 |
background:linear-gradient(90deg, rgba(77,143,204,.22), rgba(157,122,216,.18));
|
| 245 |
border-bottom:1px solid rgba(232,192,116,.5);
|
| 246 |
color:var(--amber); font-family:ui-monospace,monospace; font-size:.8rem;
|
| 247 |
letter-spacing:.05em; padding:.55rem 1rem;
|
| 248 |
-
display:flex; align-items:
|
|
|
|
|
|
|
| 249 |
#honest-banner .dot {{ width:.6rem; height:.6rem; border-radius:50%;
|
| 250 |
background:var(--amber); box-shadow:0 0 8px var(--amber); flex:0 0 auto; }}
|
| 251 |
#honest-banner b {{ color:var(--gold); }}
|
|
@@ -253,7 +254,7 @@ def _page_html(ns: str) -> str:
|
|
| 253 |
#scene {{ position:fixed; inset:0; z-index:0; }}
|
| 254 |
/* Scrollable content layer above the canvas. */
|
| 255 |
#wrap {{ position:relative; z-index:1; max-width:1180px; margin:0 auto;
|
| 256 |
-
padding:
|
| 257 |
.plaque {{ font-family:ui-monospace,monospace; font-size:.7rem; letter-spacing:.12em;
|
| 258 |
color:var(--muted); text-transform:uppercase; }}
|
| 259 |
.plaque b {{ color:var(--gold); }}
|
|
@@ -273,17 +274,18 @@ def _page_html(ns: str) -> str:
|
|
| 273 |
.lg.modeled {{ color:var(--amber); border-color:rgba(232,192,116,.45); background:rgba(232,192,116,.1); }}
|
| 274 |
.lg.roadmap {{ color:var(--violet); border-color:rgba(157,122,216,.5); background:rgba(157,122,216,.1); }}
|
| 275 |
.lg.sample {{ color:var(--indigo); border-color:rgba(77,143,204,.45); background:rgba(77,143,204,.1); }}
|
| 276 |
-
#grid {{ display:grid; grid-template-columns:repeat(auto-fill,minmax(320px,1fr));
|
| 277 |
gap:1rem; margin-top:1.2rem; }}
|
| 278 |
.card {{ background:rgba(16,26,46,.84); border:1px solid #21304d; border-radius:14px;
|
| 279 |
padding:1rem 1.1rem; box-shadow:0 18px 40px -28px #000;
|
| 280 |
backdrop-filter:blur(6px); position:relative; overflow:hidden;
|
| 281 |
-
|
| 282 |
.card::before {{ content:""; position:absolute; inset:0 0 auto 0; height:3px;
|
| 283 |
background:var(--edge,var(--indigo)); opacity:.85; }}
|
| 284 |
.card h3 {{ margin:.15rem 0 0; font-family:ui-monospace,monospace; font-size:.96rem;
|
| 285 |
color:var(--ink); display:flex; align-items:center; gap:.5rem;
|
| 286 |
-
|
|
|
|
| 287 |
.card .cat {{ font-family:ui-monospace,monospace; font-size:.62rem; letter-spacing:.1em;
|
| 288 |
text-transform:uppercase; color:var(--muted); }}
|
| 289 |
.card .stat {{ font-size:.82rem; color:var(--ink); line-height:1.4; }}
|
|
@@ -300,11 +302,70 @@ def _page_html(ns: str) -> str:
|
|
| 300 |
/* 3D-surface list — compact honest pills, one per surface. */
|
| 301 |
#surfaces-section {{ margin-top:1.6rem; }}
|
| 302 |
#surfaces-section h2 {{ font-size:clamp(1.1rem,2vw,1.4rem); margin:.2rem 0 0; }}
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
.surface-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
/* Per-tile persistent honest banner on non-MEASURED tiles. */
|
| 309 |
.tile-banner {{ font-family:ui-monospace,monospace; font-size:.66rem; line-height:1.4;
|
| 310 |
border-radius:8px; padding:.4rem .55rem; letter-spacing:.03em; }}
|
|
@@ -323,10 +384,46 @@ def _page_html(ns: str) -> str:
|
|
| 323 |
.meta b {{ color:var(--ink); }}
|
| 324 |
.status-line {{ font-family:ui-monospace,monospace; font-size:.74rem; color:var(--muted); margin-top:1.4rem; }}
|
| 325 |
.status-line.err {{ color:var(--warn); }}
|
|
|
|
| 326 |
a.back {{ color:var(--muted); text-decoration:none; font-size:.8rem; }}
|
| 327 |
a.orbital-link {{ color:var(--amber); text-decoration:none; }}
|
| 328 |
a.orbital-link:hover {{ text-decoration:underline; }}
|
| 329 |
noscript {{ color:var(--amber); display:block; padding:4rem 1.5rem; }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 330 |
</style></head>
|
| 331 |
<body>
|
| 332 |
<div id="honest-banner">
|
|
@@ -351,6 +448,48 @@ def _page_html(ns: str) -> str:
|
|
| 351 |
</div>
|
| 352 |
<div id="rollup"></div>
|
| 353 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 354 |
<!-- 3D holographic surfaces — count + honest labels, from the SAME manifest the
|
| 355 |
holographic showcase is built from (one source of truth: /frontier/surfaces). -->
|
| 356 |
<div id="surfaces-section">
|
|
@@ -359,7 +498,20 @@ def _page_html(ns: str) -> str:
|
|
| 359 |
<code>/frontier/surfaces</code> — the same machine-verifiable manifest that names each
|
| 360 |
surface's asset and its honest label (parsed from the surface source, never upgraded).</p>
|
| 361 |
<div id="surfaces-rollup"></div>
|
| 362 |
-
<div
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
<div class="status-line" id="surfaces-status">fetching /frontier/surfaces…</div>
|
| 364 |
</div>
|
| 365 |
|
|
@@ -378,6 +530,17 @@ import * as THREE from 'three';
|
|
| 378 |
import {{ OrbitControls }} from 'three/addons/OrbitControls.js';
|
| 379 |
|
| 380 |
const MANIFEST_EP = {manifest_ep!r};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 381 |
|
| 382 |
const LABEL_CLASS = {{
|
| 383 |
MEASURED:'measured', MODELED:'modeled', ROADMAP:'roadmap',
|
|
@@ -394,19 +557,22 @@ const EDGE_HEX = {{
|
|
| 394 |
|
| 395 |
function esc(s) {{ return String(s).replace(/[&<>"']/g, c =>
|
| 396 |
({{'&':'&','<':'<','>':'>','"':'"',"'":'''}}[c])); }}
|
| 397 |
-
function cls(label) {{ return LABEL_CLASS[label] || '
|
| 398 |
|
| 399 |
// ---- three.js holographic ecosystem constellation (r160, vendored, 0 CDN) ----
|
| 400 |
const canvas = document.getElementById('scene');
|
| 401 |
const renderer = new THREE.WebGLRenderer({{ canvas, antialias:true, alpha:true }});
|
| 402 |
-
|
|
|
|
|
|
|
| 403 |
const scene = new THREE.Scene();
|
| 404 |
const camera = new THREE.PerspectiveCamera(55, 1, 0.1, 2000);
|
| 405 |
camera.position.set(0, 6, 60);
|
| 406 |
const controls = new OrbitControls(camera, canvas);
|
| 407 |
controls.enableDamping = true; controls.dampingFactor = 0.06;
|
| 408 |
controls.enablePan = false; controls.enableZoom = false;
|
| 409 |
-
controls.autoRotate =
|
|
|
|
| 410 |
|
| 411 |
scene.add(new THREE.AmbientLight(0x88aacc, 0.7));
|
| 412 |
const key = new THREE.PointLight(0xffffff, 1.1); key.position.set(40, 50, 50); scene.add(key);
|
|
@@ -429,12 +595,29 @@ function resize() {{
|
|
| 429 |
}}
|
| 430 |
addEventListener('resize', resize); resize();
|
| 431 |
|
| 432 |
-
|
| 433 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 434 |
controls.update();
|
| 435 |
core.rotation.y += 0.0012; core.rotation.x += 0.0005;
|
| 436 |
renderer.render(scene, camera);
|
| 437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
|
| 439 |
// Place capability tiles evenly on a ring around the core, colored by honest label.
|
| 440 |
function drawConstellation(tiles) {{
|
|
@@ -520,6 +703,87 @@ function fail(msg) {{
|
|
| 520 |
if (el) {{ el.className = 'status-line err'; el.textContent = msg; }}
|
| 521 |
}}
|
| 522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 523 |
(async function load() {{
|
| 524 |
try {{
|
| 525 |
const r = await fetch(MANIFEST_EP, {{ headers:{{Accept:'application/json'}} }});
|
|
@@ -563,6 +827,93 @@ const SURF_CLASS = {{
|
|
| 563 |
}};
|
| 564 |
function surfCls(label) {{ return SURF_CLASS[label] || 'unavailable'; }}
|
| 565 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 566 |
(async function loadSurfaces() {{
|
| 567 |
const statusEl = document.getElementById('surfaces-status');
|
| 568 |
try {{
|
|
@@ -581,14 +932,10 @@ function surfCls(label) {{ return SURF_CLASS[label] || 'unavailable'; }}
|
|
| 581 |
chips.push(`<span class="chip">labels valid: <b>${{esc(String(s.labels_valid))}}</b></span>`);
|
| 582 |
document.getElementById('surfaces-rollup').innerHTML = chips.join('');
|
| 583 |
|
| 584 |
-
//
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
+ `<span class="sid">${{esc(su.id)}}</span>`
|
| 589 |
-
+ `<span>${{esc(su.title || '')}}</span>`
|
| 590 |
-
+ `<span class="badge ${{surfCls(label)}}">${{esc(label)}}</span></span>`;
|
| 591 |
-
}}).join('');
|
| 592 |
|
| 593 |
statusEl.className = 'status-line';
|
| 594 |
statusEl.textContent = (m.ok === false)
|
|
@@ -596,6 +943,9 @@ function surfCls(label) {{ return SURF_CLASS[label] || 'unavailable'; }}
|
|
| 596 |
: ('live · ' + esc(m.count ?? surfaces.length) + ' surfaces from ' + esc(SURFACES_EP)
|
| 597 |
+ ' · labels_valid=' + esc(String(s.labels_valid)));
|
| 598 |
}} catch (e) {{
|
|
|
|
|
|
|
|
|
|
| 599 |
statusEl.className = 'status-line err';
|
| 600 |
statusEl.textContent = 'surfaces unavailable: ' + e + ' (nothing fabricated — raw data at ' + SURFACES_EP + ')';
|
| 601 |
}}
|
|
@@ -604,16 +954,20 @@ function surfCls(label) {{ return SURF_CLASS[label] || 'unavailable'; }}
|
|
| 604 |
</body></html>"""
|
| 605 |
|
| 606 |
|
| 607 |
-
def register(app
|
| 608 |
"""Mount GET /frontier (HTML) + GET /api/<ns>/v1/frontier/page-manifest (JSON).
|
| 609 |
ADDITIVE — registered before the SPA catch-all; touches no existing route."""
|
| 610 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
@app.get("/frontier", include_in_schema=False)
|
| 612 |
-
async def frontier_page()
|
| 613 |
return HTMLResponse(_page_html(ns))
|
| 614 |
|
| 615 |
@app.get(f"/api/{ns}/v1/frontier/surfaces")
|
| 616 |
-
async def frontier_surfaces()
|
| 617 |
"""Machine-verifiable manifest of every 3D frontier surface.
|
| 618 |
|
| 619 |
id + title + honesty label (parsed from the surface source, verbatim) +
|
|
@@ -621,7 +975,7 @@ def register(app: FastAPI, ns: str = "a11oy") -> str:
|
|
| 621 |
return JSONResponse(build_surfaces_manifest(ns))
|
| 622 |
|
| 623 |
@app.get(f"/api/{ns}/v1/frontier/page-manifest", include_in_schema=False)
|
| 624 |
-
async def frontier_page_manifest()
|
| 625 |
return JSONResponse({
|
| 626 |
"section": "Frontier",
|
| 627 |
"page": "/frontier",
|
|
@@ -667,8 +1021,35 @@ def _selftest() -> None:
|
|
| 667 |
assert 'id="surfaces-list"' in html and 'id="surfaces-rollup"' in html, \
|
| 668 |
"surfaces section markers missing"
|
| 669 |
assert "loadSurfaces" in html, "surfaces client loader missing"
|
| 670 |
-
|
| 671 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 672 |
man = build_surfaces_manifest("a11oy")
|
| 673 |
assert man["ok"] is True, f"surfaces manifest not ok: {man.get('error')}"
|
| 674 |
assert man["count"] == len(man["surfaces"]) and man["count"] > 0, "surface count mismatch"
|
|
|
|
| 47 |
import pathlib
|
| 48 |
import re
|
| 49 |
|
|
|
|
|
|
|
|
|
|
| 50 |
DOCTRINE = {"version": "v11", "lambda": "Conjecture 1", "sovereign": False}
|
| 51 |
|
| 52 |
# --------------------------------------------------------------------------- #
|
|
|
|
| 230 |
<style>
|
| 231 |
:root {{ --bg:#070b16; --panel:#101a2e; --ink:#e8eef7; --muted:#8aa0bd;
|
| 232 |
--indigo:#4d8fcc; --terra:#c8643c; --gold:#d8a23c; --amber:#e8c074;
|
| 233 |
+
--green:#2fd07a; --warn:#c8893c; --violet:#9d7ad8; --red:#d8624a;
|
| 234 |
+
--honest-banner-h:3.1rem; }}
|
| 235 |
* {{ box-sizing:border-box; }}
|
| 236 |
+
html,body {{ margin:0; min-height:100%; max-width:100%; }}
|
| 237 |
+
html {{ overflow-x:clip; scroll-padding-top:calc(var(--honest-banner-h) + 1rem); }}
|
| 238 |
body {{ font-family:ui-sans-serif,system-ui,Segoe UI,Roboto,sans-serif;
|
| 239 |
+
background:radial-gradient(1200px 700px at 70% -10%, #14213b, var(--bg));
|
| 240 |
+
color:var(--ink); overflow-x:hidden; }}
|
| 241 |
/* Persistent, unmissable HONEST banner — top of every viewport. */
|
| 242 |
#honest-banner {{ position:fixed; top:0; left:0; right:0; z-index:50;
|
| 243 |
background:linear-gradient(90deg, rgba(77,143,204,.22), rgba(157,122,216,.18));
|
| 244 |
border-bottom:1px solid rgba(232,192,116,.5);
|
| 245 |
color:var(--amber); font-family:ui-monospace,monospace; font-size:.8rem;
|
| 246 |
letter-spacing:.05em; padding:.55rem 1rem;
|
| 247 |
+
display:flex; align-items:flex-start; gap:.6rem; line-height:1.4;
|
| 248 |
+
backdrop-filter:blur(4px); overflow-wrap:anywhere; }}
|
| 249 |
+
#honest-banner > span:last-child {{ min-width:0; }}
|
| 250 |
#honest-banner .dot {{ width:.6rem; height:.6rem; border-radius:50%;
|
| 251 |
background:var(--amber); box-shadow:0 0 8px var(--amber); flex:0 0 auto; }}
|
| 252 |
#honest-banner b {{ color:var(--gold); }}
|
|
|
|
| 254 |
#scene {{ position:fixed; inset:0; z-index:0; }}
|
| 255 |
/* Scrollable content layer above the canvas. */
|
| 256 |
#wrap {{ position:relative; z-index:1; max-width:1180px; margin:0 auto;
|
| 257 |
+
padding:calc(var(--honest-banner-h) + 1.1rem) 1.2rem 4rem; min-width:0; }}
|
| 258 |
.plaque {{ font-family:ui-monospace,monospace; font-size:.7rem; letter-spacing:.12em;
|
| 259 |
color:var(--muted); text-transform:uppercase; }}
|
| 260 |
.plaque b {{ color:var(--gold); }}
|
|
|
|
| 274 |
.lg.modeled {{ color:var(--amber); border-color:rgba(232,192,116,.45); background:rgba(232,192,116,.1); }}
|
| 275 |
.lg.roadmap {{ color:var(--violet); border-color:rgba(157,122,216,.5); background:rgba(157,122,216,.1); }}
|
| 276 |
.lg.sample {{ color:var(--indigo); border-color:rgba(77,143,204,.45); background:rgba(77,143,204,.1); }}
|
| 277 |
+
#grid {{ display:grid; grid-template-columns:repeat(auto-fill,minmax(min(100%,320px),1fr));
|
| 278 |
gap:1rem; margin-top:1.2rem; }}
|
| 279 |
.card {{ background:rgba(16,26,46,.84); border:1px solid #21304d; border-radius:14px;
|
| 280 |
padding:1rem 1.1rem; box-shadow:0 18px 40px -28px #000;
|
| 281 |
backdrop-filter:blur(6px); position:relative; overflow:hidden;
|
| 282 |
+
display:flex; flex-direction:column; gap:.55rem; min-width:0; }}
|
| 283 |
.card::before {{ content:""; position:absolute; inset:0 0 auto 0; height:3px;
|
| 284 |
background:var(--edge,var(--indigo)); opacity:.85; }}
|
| 285 |
.card h3 {{ margin:.15rem 0 0; font-family:ui-monospace,monospace; font-size:.96rem;
|
| 286 |
color:var(--ink); display:flex; align-items:center; gap:.5rem;
|
| 287 |
+
justify-content:space-between; }}
|
| 288 |
+
.card h3 > span:first-child {{ min-width:0; overflow-wrap:anywhere; }}
|
| 289 |
.card .cat {{ font-family:ui-monospace,monospace; font-size:.62rem; letter-spacing:.1em;
|
| 290 |
text-transform:uppercase; color:var(--muted); }}
|
| 291 |
.card .stat {{ font-size:.82rem; color:var(--ink); line-height:1.4; }}
|
|
|
|
| 302 |
/* 3D-surface list — compact honest pills, one per surface. */
|
| 303 |
#surfaces-section {{ margin-top:1.6rem; }}
|
| 304 |
#surfaces-section h2 {{ font-size:clamp(1.1rem,2vw,1.4rem); margin:.2rem 0 0; }}
|
| 305 |
+
.surface-tools {{ display:grid; grid-template-columns:minmax(0,1fr) minmax(220px,300px);
|
| 306 |
+
gap:.75rem; align-items:end; margin-top:1rem; min-width:0; }}
|
| 307 |
+
.surface-tabs {{ display:flex; gap:.4rem; overflow-x:auto; padding:.15rem .1rem .45rem;
|
| 308 |
+
min-width:0; scrollbar-width:thin; overscroll-behavior-inline:contain; }}
|
| 309 |
+
.surface-tab {{ border:1px solid #21304d; border-radius:999px; padding:.42rem .72rem;
|
| 310 |
+
color:var(--muted); background:rgba(7,12,23,.7); font:600 .66rem/1 ui-monospace,monospace;
|
| 311 |
+
letter-spacing:.04em; white-space:nowrap; cursor:pointer; }}
|
| 312 |
+
.surface-tab[aria-selected="true"] {{ color:var(--ink); border-color:var(--gold);
|
| 313 |
+
background:rgba(216,162,60,.14); }}
|
| 314 |
+
.surface-search {{ display:grid; gap:.35rem; min-width:0; color:var(--muted);
|
| 315 |
+
font:600 .62rem/1.2 ui-monospace,monospace; letter-spacing:.08em; text-transform:uppercase; }}
|
| 316 |
+
.surface-search input {{ width:100%; min-width:0; border:1px solid #2b3d60; border-radius:9px;
|
| 317 |
+
padding:.62rem .72rem; background:rgba(7,12,23,.86); color:var(--ink); font:inherit;
|
| 318 |
+
letter-spacing:0; text-transform:none; }}
|
| 319 |
+
#surfaces-list {{ display:grid; grid-template-columns:repeat(auto-fill,minmax(min(100%,250px),1fr));
|
| 320 |
+
gap:.6rem; margin-top:1rem; min-width:0; }}
|
| 321 |
+
.surface-pill {{ display:grid; grid-template-columns:minmax(0,1fr) auto; gap:.45rem .65rem;
|
| 322 |
+
align-items:start; min-width:0; background:rgba(16,26,46,.84); border:1px solid #21304d;
|
| 323 |
+
border-radius:11px; padding:.7rem .75rem; font-family:ui-monospace,monospace;
|
| 324 |
+
font-size:.72rem; color:var(--ink); text-decoration:none; overflow:hidden; }}
|
| 325 |
+
.surface-pill:hover {{ border-color:#3b537d; background:rgba(20,34,59,.92); }}
|
| 326 |
+
.surface-pill .surface-copy {{ min-width:0; display:grid; gap:.22rem; }}
|
| 327 |
+
.surface-pill .sid {{ color:var(--muted); overflow-wrap:anywhere; }}
|
| 328 |
+
.surface-pill .surface-title {{ min-width:0; line-height:1.35; overflow-wrap:anywhere; }}
|
| 329 |
+
.surface-pagination {{ display:flex; justify-content:space-between; align-items:center; gap:.75rem;
|
| 330 |
+
margin-top:.8rem; min-width:0; }}
|
| 331 |
+
.surface-pagination button {{ border:1px solid #2b3d60; border-radius:8px; padding:.46rem .72rem;
|
| 332 |
+
background:rgba(7,12,23,.82); color:var(--ink); font:600 .66rem/1 ui-monospace,monospace;
|
| 333 |
+
cursor:pointer; }}
|
| 334 |
+
.surface-pagination button:disabled {{ opacity:.38; cursor:not-allowed; }}
|
| 335 |
+
#surface-page-status {{ min-width:0; color:var(--muted); text-align:center;
|
| 336 |
+
font:500 .66rem/1.35 ui-monospace,monospace; overflow-wrap:anywhere; }}
|
| 337 |
+
.surface-empty {{ grid-column:1/-1; padding:1rem; border:1px dashed #2b3d60;
|
| 338 |
+
border-radius:10px; color:var(--muted); font:500 .72rem/1.5 ui-monospace,monospace; }}
|
| 339 |
+
#brain-section {{ margin-top:1.6rem; }}
|
| 340 |
+
.brain-shell {{ margin-top:.9rem; padding:1rem; border:1px solid #263858; border-radius:14px;
|
| 341 |
+
background:linear-gradient(145deg,rgba(16,26,46,.9),rgba(7,12,23,.88)); min-width:0; }}
|
| 342 |
+
.brain-head {{ display:flex; justify-content:space-between; gap:1rem; align-items:flex-start; }}
|
| 343 |
+
.brain-head > div {{ min-width:0; }}
|
| 344 |
+
.brain-head h2 {{ margin:0; font-size:clamp(1.1rem,2vw,1.4rem); }}
|
| 345 |
+
.brain-metrics {{ display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:.55rem;
|
| 346 |
+
margin-top:.9rem; }}
|
| 347 |
+
.brain-metric {{ min-width:0; padding:.7rem; border:1px solid #21304d; border-radius:9px;
|
| 348 |
+
background:rgba(7,12,23,.64); }}
|
| 349 |
+
.brain-value {{ display:block; color:var(--ink); font:700 clamp(.9rem,2vw,1.15rem)/1.2 ui-monospace,monospace;
|
| 350 |
+
overflow-wrap:anywhere; }}
|
| 351 |
+
.brain-key {{ display:block; margin-top:.28rem; color:var(--muted);
|
| 352 |
+
font:500 .58rem/1.35 ui-monospace,monospace; letter-spacing:.06em; text-transform:uppercase; }}
|
| 353 |
+
.brain-flow {{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:.45rem;
|
| 354 |
+
margin-top:.8rem; }}
|
| 355 |
+
.brain-step {{ min-width:0; padding:.6rem; border-radius:8px; border:1px solid rgba(77,143,204,.25);
|
| 356 |
+
color:#b9c9dd; font:500 .66rem/1.4 ui-monospace,monospace; overflow-wrap:anywhere; }}
|
| 357 |
+
.brain-step b {{ display:block; color:var(--indigo); margin-bottom:.18rem; }}
|
| 358 |
+
.brain-query {{ display:grid; grid-template-columns:minmax(0,1fr) auto; gap:.55rem; margin-top:.8rem; }}
|
| 359 |
+
.brain-query input {{ min-width:0; width:100%; border:1px solid #2b3d60; border-radius:9px;
|
| 360 |
+
padding:.7rem .75rem; background:#070c17; color:var(--ink); }}
|
| 361 |
+
.brain-query button {{ border:1px solid rgba(216,162,60,.55); border-radius:9px; padding:.65rem .85rem;
|
| 362 |
+
background:rgba(216,162,60,.12); color:var(--amber); font:600 .7rem/1 ui-monospace,monospace;
|
| 363 |
+
cursor:pointer; }}
|
| 364 |
+
#brain-result {{ margin-top:.65rem; min-width:0; padding:.65rem .75rem; border-radius:9px;
|
| 365 |
+
border:1px solid #1a2742; background:#070c17; color:#b9c9dd;
|
| 366 |
+
font:500 .68rem/1.5 ui-monospace,monospace; overflow-wrap:anywhere; }}
|
| 367 |
+
.brain-links {{ display:flex; flex-wrap:wrap; gap:.45rem .8rem; margin-top:.7rem; }}
|
| 368 |
+
.brain-links a {{ color:var(--green); font:500 .68rem/1.4 ui-monospace,monospace; text-underline-offset:3px; }}
|
| 369 |
/* Per-tile persistent honest banner on non-MEASURED tiles. */
|
| 370 |
.tile-banner {{ font-family:ui-monospace,monospace; font-size:.66rem; line-height:1.4;
|
| 371 |
border-radius:8px; padding:.4rem .55rem; letter-spacing:.03em; }}
|
|
|
|
| 384 |
.meta b {{ color:var(--ink); }}
|
| 385 |
.status-line {{ font-family:ui-monospace,monospace; font-size:.74rem; color:var(--muted); margin-top:1.4rem; }}
|
| 386 |
.status-line.err {{ color:var(--warn); }}
|
| 387 |
+
:where(a,button,input):focus-visible {{ outline:2px solid var(--gold); outline-offset:3px; }}
|
| 388 |
a.back {{ color:var(--muted); text-decoration:none; font-size:.8rem; }}
|
| 389 |
a.orbital-link {{ color:var(--amber); text-decoration:none; }}
|
| 390 |
a.orbital-link:hover {{ text-decoration:underline; }}
|
| 391 |
noscript {{ color:var(--amber); display:block; padding:4rem 1.5rem; }}
|
| 392 |
+
@media (max-width:900px) {{
|
| 393 |
+
.brain-metrics {{ grid-template-columns:repeat(3,minmax(0,1fr)); }}
|
| 394 |
+
}}
|
| 395 |
+
@media (max-width:720px) {{
|
| 396 |
+
:root {{ --honest-banner-h:6.8rem; }}
|
| 397 |
+
#honest-banner {{ padding:.5rem .7rem; font-size:.66rem; letter-spacing:.025em; }}
|
| 398 |
+
#scene {{ opacity:.22; pointer-events:none; }}
|
| 399 |
+
#wrap {{ padding-left:.75rem; padding-right:.75rem; }}
|
| 400 |
+
.surface-tools {{ grid-template-columns:minmax(0,1fr); }}
|
| 401 |
+
.surface-tabs {{ width:100%; }}
|
| 402 |
+
#surfaces-list, #grid {{ grid-template-columns:minmax(0,1fr); }}
|
| 403 |
+
.surface-pill {{ padding:.65rem; }}
|
| 404 |
+
.surface-pagination {{ align-items:stretch; }}
|
| 405 |
+
.surface-pagination button {{ flex:0 0 auto; }}
|
| 406 |
+
#surface-page-status {{ align-self:center; }}
|
| 407 |
+
.brain-metrics {{ grid-template-columns:repeat(2,minmax(0,1fr)); }}
|
| 408 |
+
.brain-flow {{ grid-template-columns:repeat(2,minmax(0,1fr)); }}
|
| 409 |
+
}}
|
| 410 |
+
@media (max-width:420px) {{
|
| 411 |
+
:root {{ --honest-banner-h:7.4rem; }}
|
| 412 |
+
.plaque {{ font-size:.62rem; letter-spacing:.08em; }}
|
| 413 |
+
h1 {{ font-size:1.65rem; }}
|
| 414 |
+
#legend, #rollup {{ gap:.35rem; }}
|
| 415 |
+
.surface-pagination {{ display:grid; grid-template-columns:1fr 1fr; }}
|
| 416 |
+
#surface-page-status {{ grid-column:1/-1; grid-row:1; }}
|
| 417 |
+
.brain-head {{ display:grid; }}
|
| 418 |
+
.brain-metrics, .brain-flow {{ grid-template-columns:minmax(0,1fr); }}
|
| 419 |
+
.brain-query {{ grid-template-columns:minmax(0,1fr); }}
|
| 420 |
+
}}
|
| 421 |
+
@media (prefers-reduced-motion:reduce) {{
|
| 422 |
+
html {{ scroll-behavior:auto; }}
|
| 423 |
+
#scene {{ display:none; }}
|
| 424 |
+
*, *::before, *::after {{ animation-duration:.01ms !important; animation-iteration-count:1 !important;
|
| 425 |
+
transition-duration:.01ms !important; }}
|
| 426 |
+
}}
|
| 427 |
</style></head>
|
| 428 |
<body>
|
| 429 |
<div id="honest-banner">
|
|
|
|
| 448 |
</div>
|
| 449 |
<div id="rollup"></div>
|
| 450 |
|
| 451 |
+
<section id="brain-section" aria-labelledby="brain-h">
|
| 452 |
+
<div class="brain-shell">
|
| 453 |
+
<div class="brain-head">
|
| 454 |
+
<div>
|
| 455 |
+
<div class="plaque">Evidence Brain / live governed reads</div>
|
| 456 |
+
<h2 id="brain-h">From indexed evidence to an answer or an honest abstention</h2>
|
| 457 |
+
<p class="sub">Counts come from the live Brain and corpus-admission APIs. Query round-trip
|
| 458 |
+
time is shown only after a real request. A dormant-to-active delta stays unavailable
|
| 459 |
+
until comparable before/after ingestion receipts exist.</p>
|
| 460 |
+
</div>
|
| 461 |
+
<span class="badge unavailable" id="brain-label">UNAVAILABLE</span>
|
| 462 |
+
</div>
|
| 463 |
+
<div class="brain-metrics" aria-label="Evidence Brain metrics">
|
| 464 |
+
<div class="brain-metric"><span class="brain-value" id="brain-node-count">--</span><span class="brain-key">Raw evidence nodes</span></div>
|
| 465 |
+
<div class="brain-metric"><span class="brain-value" id="brain-artifact-count">--</span><span class="brain-key">Distinct artifacts</span></div>
|
| 466 |
+
<div class="brain-metric"><span class="brain-value" id="brain-admitted-count">--</span><span class="brain-key">Governed corpus entries</span></div>
|
| 467 |
+
<div class="brain-metric"><span class="brain-value" id="brain-quarantine-count">--</span><span class="brain-key">Quarantined entries</span></div>
|
| 468 |
+
<div class="brain-metric"><span class="brain-value" id="brain-query-latency">NOT RUN</span><span class="brain-key">Measured client query RTT</span></div>
|
| 469 |
+
<div class="brain-metric"><span class="brain-value" id="brain-ingestion-delta">NOT MEASURED</span><span class="brain-key">Dormant to active delta</span></div>
|
| 470 |
+
</div>
|
| 471 |
+
<div class="brain-flow" aria-label="Source-grounded answer flow">
|
| 472 |
+
<div class="brain-step"><b>01 Query</b>bounded user question</div>
|
| 473 |
+
<div class="brain-step"><b>02 Retrieve</b>ranked graph evidence</div>
|
| 474 |
+
<div class="brain-step"><b>03 Ground</b>cited node identifiers</div>
|
| 475 |
+
<div class="brain-step"><b>04 Decide</b>MODELED answer or UNAVAILABLE</div>
|
| 476 |
+
</div>
|
| 477 |
+
<form class="brain-query" id="brain-query-form">
|
| 478 |
+
<label class="plaque" for="brain-query-input" style="position:absolute;left:-10000px">Evidence Brain question</label>
|
| 479 |
+
<input id="brain-query-input" name="q" type="search" autocomplete="off"
|
| 480 |
+
placeholder="Ask the graph; answers must cite retrieved node IDs"/>
|
| 481 |
+
<button type="submit">Run grounded query</button>
|
| 482 |
+
</form>
|
| 483 |
+
<div id="brain-result" role="status" aria-live="polite">Loading live Brain and corpus-admission status...</div>
|
| 484 |
+
<div class="brain-links">
|
| 485 |
+
<a href="/holographic#brainquery">Open Brain Query tab →</a>
|
| 486 |
+
<a href="/formulas">Inspect formula registry →</a>
|
| 487 |
+
<a href="/api/a11oy/v1/brain/stats">Raw Brain stats →</a>
|
| 488 |
+
<a href="/api/a11oy/v1/brain/health/corpus-sources">Corpus admission evidence →</a>
|
| 489 |
+
</div>
|
| 490 |
+
</div>
|
| 491 |
+
</section>
|
| 492 |
+
|
| 493 |
<!-- 3D holographic surfaces — count + honest labels, from the SAME manifest the
|
| 494 |
holographic showcase is built from (one source of truth: /frontier/surfaces). -->
|
| 495 |
<div id="surfaces-section">
|
|
|
|
| 498 |
<code>/frontier/surfaces</code> — the same machine-verifiable manifest that names each
|
| 499 |
surface's asset and its honest label (parsed from the surface source, never upgraded).</p>
|
| 500 |
<div id="surfaces-rollup"></div>
|
| 501 |
+
<div class="surface-tools">
|
| 502 |
+
<div class="surface-tabs" id="surface-filters" role="tablist"
|
| 503 |
+
aria-label="Filter holographic surfaces by honest label"></div>
|
| 504 |
+
<label class="surface-search" for="surface-search">Find any surface
|
| 505 |
+
<input id="surface-search" type="search" autocomplete="off"
|
| 506 |
+
placeholder="Search ID or title"/>
|
| 507 |
+
</label>
|
| 508 |
+
</div>
|
| 509 |
+
<div id="surfaces-list" role="list" aria-label="Holographic surface catalog"></div>
|
| 510 |
+
<nav class="surface-pagination" id="surface-pagination" aria-label="Holographic surface pages">
|
| 511 |
+
<button id="surface-prev" type="button">← Previous</button>
|
| 512 |
+
<span id="surface-page-status" aria-live="polite">Waiting for surface manifest...</span>
|
| 513 |
+
<button id="surface-next" type="button">Next →</button>
|
| 514 |
+
</nav>
|
| 515 |
<div class="status-line" id="surfaces-status">fetching /frontier/surfaces…</div>
|
| 516 |
</div>
|
| 517 |
|
|
|
|
| 530 |
import {{ OrbitControls }} from 'three/addons/OrbitControls.js';
|
| 531 |
|
| 532 |
const MANIFEST_EP = {manifest_ep!r};
|
| 533 |
+
const BRAIN_STATS_EP = '/api/a11oy/v1/brain/stats';
|
| 534 |
+
const BRAIN_CORPUS_EP = '/api/a11oy/v1/brain/health/corpus-sources';
|
| 535 |
+
const BRAIN_ASK_EP = '/api/a11oy/v1/brain/ask';
|
| 536 |
+
const banner = document.getElementById('honest-banner');
|
| 537 |
+
function syncBannerOffset() {{
|
| 538 |
+
const height = banner ? Math.ceil(banner.getBoundingClientRect().height) : 0;
|
| 539 |
+
if (height > 0) document.documentElement.style.setProperty('--honest-banner-h', height + 'px');
|
| 540 |
+
}}
|
| 541 |
+
if ('ResizeObserver' in window && banner) new ResizeObserver(syncBannerOffset).observe(banner);
|
| 542 |
+
addEventListener('resize', syncBannerOffset, {{passive:true}});
|
| 543 |
+
syncBannerOffset();
|
| 544 |
|
| 545 |
const LABEL_CLASS = {{
|
| 546 |
MEASURED:'measured', MODELED:'modeled', ROADMAP:'roadmap',
|
|
|
|
| 557 |
|
| 558 |
function esc(s) {{ return String(s).replace(/[&<>"']/g, c =>
|
| 559 |
({{'&':'&','<':'<','>':'>','"':'"',"'":'''}}[c])); }}
|
| 560 |
+
function cls(label) {{ return LABEL_CLASS[label] || 'unavailable'; }}
|
| 561 |
|
| 562 |
// ---- three.js holographic ecosystem constellation (r160, vendored, 0 CDN) ----
|
| 563 |
const canvas = document.getElementById('scene');
|
| 564 |
const renderer = new THREE.WebGLRenderer({{ canvas, antialias:true, alpha:true }});
|
| 565 |
+
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)');
|
| 566 |
+
const compactCanvas = matchMedia('(max-width: 720px)');
|
| 567 |
+
renderer.setPixelRatio(Math.min(devicePixelRatio, compactCanvas.matches ? 1 : 2));
|
| 568 |
const scene = new THREE.Scene();
|
| 569 |
const camera = new THREE.PerspectiveCamera(55, 1, 0.1, 2000);
|
| 570 |
camera.position.set(0, 6, 60);
|
| 571 |
const controls = new OrbitControls(camera, canvas);
|
| 572 |
controls.enableDamping = true; controls.dampingFactor = 0.06;
|
| 573 |
controls.enablePan = false; controls.enableZoom = false;
|
| 574 |
+
controls.autoRotate = !(reducedMotion.matches || compactCanvas.matches);
|
| 575 |
+
controls.autoRotateSpeed = 0.28;
|
| 576 |
|
| 577 |
scene.add(new THREE.AmbientLight(0x88aacc, 0.7));
|
| 578 |
const key = new THREE.PointLight(0xffffff, 1.1); key.position.set(40, 50, 50); scene.add(key);
|
|
|
|
| 595 |
}}
|
| 596 |
addEventListener('resize', resize); resize();
|
| 597 |
|
| 598 |
+
let animationFrame = 0;
|
| 599 |
+
function renderFrame() {{
|
| 600 |
+
animationFrame = 0;
|
| 601 |
+
if (document.hidden || reducedMotion.matches || compactCanvas.matches) {{
|
| 602 |
+
renderer.render(scene, camera);
|
| 603 |
+
return;
|
| 604 |
+
}}
|
| 605 |
controls.update();
|
| 606 |
core.rotation.y += 0.0012; core.rotation.x += 0.0005;
|
| 607 |
renderer.render(scene, camera);
|
| 608 |
+
animationFrame = requestAnimationFrame(renderFrame);
|
| 609 |
+
}}
|
| 610 |
+
function applyMotionPolicy() {{
|
| 611 |
+
controls.autoRotate = !(reducedMotion.matches || compactCanvas.matches);
|
| 612 |
+
renderer.setPixelRatio(Math.min(devicePixelRatio, compactCanvas.matches ? 1 : 2));
|
| 613 |
+
if (animationFrame) cancelAnimationFrame(animationFrame);
|
| 614 |
+
animationFrame = 0;
|
| 615 |
+
renderFrame();
|
| 616 |
+
}}
|
| 617 |
+
reducedMotion.addEventListener?.('change', applyMotionPolicy);
|
| 618 |
+
compactCanvas.addEventListener?.('change', applyMotionPolicy);
|
| 619 |
+
document.addEventListener('visibilitychange', applyMotionPolicy);
|
| 620 |
+
applyMotionPolicy();
|
| 621 |
|
| 622 |
// Place capability tiles evenly on a ring around the core, colored by honest label.
|
| 623 |
function drawConstellation(tiles) {{
|
|
|
|
| 703 |
if (el) {{ el.className = 'status-line err'; el.textContent = msg; }}
|
| 704 |
}}
|
| 705 |
|
| 706 |
+
function setBrainMetric(id, value) {{
|
| 707 |
+
const el = document.getElementById(id);
|
| 708 |
+
if (el) el.textContent = value == null ? '--' : String(value);
|
| 709 |
+
}}
|
| 710 |
+
function setBrainLabel(label) {{
|
| 711 |
+
const honest = label || 'UNAVAILABLE';
|
| 712 |
+
const el = document.getElementById('brain-label');
|
| 713 |
+
if (el) {{ el.textContent = honest; el.className = 'badge ' + cls(honest); }}
|
| 714 |
+
}}
|
| 715 |
+
|
| 716 |
+
(async function loadEvidenceBrain() {{
|
| 717 |
+
const result = document.getElementById('brain-result');
|
| 718 |
+
try {{
|
| 719 |
+
const [statsResponse, corpusResponse] = await Promise.all([
|
| 720 |
+
fetch(BRAIN_STATS_EP, {{headers:{{Accept:'application/json'}}}}),
|
| 721 |
+
fetch(BRAIN_CORPUS_EP, {{headers:{{Accept:'application/json'}}}}),
|
| 722 |
+
]);
|
| 723 |
+
if (!statsResponse.ok || !corpusResponse.ok) throw new Error(
|
| 724 |
+
'status endpoints ' + statsResponse.status + '/' + corpusResponse.status);
|
| 725 |
+
const stats = await statsResponse.json();
|
| 726 |
+
const corpus = await corpusResponse.json();
|
| 727 |
+
const counts = corpus?.summary?.counts || {{}};
|
| 728 |
+
const admitted = Object.values(counts).reduce((total, value) => total + (Number(value) || 0), 0);
|
| 729 |
+
setBrainMetric('brain-node-count', stats.node_count);
|
| 730 |
+
setBrainMetric('brain-artifact-count', stats.distinct_artifacts);
|
| 731 |
+
setBrainMetric('brain-admitted-count', admitted);
|
| 732 |
+
setBrainMetric('brain-quarantine-count', corpus?.summary?.quarantined_entries);
|
| 733 |
+
setBrainMetric('brain-ingestion-delta', 'NOT MEASURED');
|
| 734 |
+
setBrainLabel(stats.label);
|
| 735 |
+
result.textContent = 'Live status loaded. Brain counts are ' + (stats.label || 'UNAVAILABLE') +
|
| 736 |
+
'; corpus admission is ' + (corpus.label || 'UNAVAILABLE') +
|
| 737 |
+
'. Raw graph and governed-corpus counts are different contracts; no ingestion uplift is inferred.';
|
| 738 |
+
}} catch (error) {{
|
| 739 |
+
setBrainLabel('UNAVAILABLE');
|
| 740 |
+
result.textContent = 'Brain status unavailable: ' + error + '. No counts or ingestion delta fabricated.';
|
| 741 |
+
}}
|
| 742 |
+
}})();
|
| 743 |
+
|
| 744 |
+
document.getElementById('brain-query-form').addEventListener('submit', async event => {{
|
| 745 |
+
event.preventDefault();
|
| 746 |
+
const input = document.getElementById('brain-query-input');
|
| 747 |
+
const button = event.currentTarget.querySelector('button');
|
| 748 |
+
const result = document.getElementById('brain-result');
|
| 749 |
+
const q = input.value.trim();
|
| 750 |
+
if (!q) {{
|
| 751 |
+
result.textContent = 'Enter a non-empty question. No query was run and no latency was inferred.';
|
| 752 |
+
return;
|
| 753 |
+
}}
|
| 754 |
+
button.disabled = true;
|
| 755 |
+
result.textContent = 'Running a source-grounded Brain query...';
|
| 756 |
+
const started = performance.now();
|
| 757 |
+
try {{
|
| 758 |
+
const response = await fetch(BRAIN_ASK_EP + '?q=' + encodeURIComponent(q) + '&k=12',
|
| 759 |
+
{{headers:{{Accept:'application/json'}}}});
|
| 760 |
+
const payload = await response.json();
|
| 761 |
+
if (!response.ok) throw new Error('query ' + response.status);
|
| 762 |
+
const elapsed = Math.round(performance.now() - started);
|
| 763 |
+
setBrainMetric('brain-query-latency', elapsed + ' ms');
|
| 764 |
+
const answerLabel = payload.answer_label || 'UNAVAILABLE';
|
| 765 |
+
const cited = Array.isArray(payload.cited_node_ids) ? payload.cited_node_ids.slice(0, 12) : [];
|
| 766 |
+
const groundingCount = payload?.grounding_subgraph?.node_count ?? cited.length;
|
| 767 |
+
const prose = typeof payload.answer === 'string' && payload.answer.trim()
|
| 768 |
+
? payload.answer.trim().slice(0, 600) : '';
|
| 769 |
+
setBrainLabel(answerLabel);
|
| 770 |
+
result.textContent = prose
|
| 771 |
+
? '[' + answerLabel + '] ' + prose + ' | cited: ' + (cited.join(', ') || 'none') +
|
| 772 |
+
' | measured client RTT: ' + elapsed + ' ms'
|
| 773 |
+
: '[' + answerLabel + '] Grounding returned ' + groundingCount + ' nodes (' +
|
| 774 |
+
(cited.join(', ') || 'no cited IDs') + '). No generated prose was available; nothing fabricated. ' +
|
| 775 |
+
'Measured client RTT: ' + elapsed + ' ms.';
|
| 776 |
+
}} catch (error) {{
|
| 777 |
+
const elapsed = Math.round(performance.now() - started);
|
| 778 |
+
setBrainMetric('brain-query-latency', elapsed + ' ms');
|
| 779 |
+
setBrainLabel('UNAVAILABLE');
|
| 780 |
+
result.textContent = 'Brain query unavailable after a measured ' + elapsed + ' ms: ' + error +
|
| 781 |
+
'. No answer fabricated.';
|
| 782 |
+
}} finally {{
|
| 783 |
+
button.disabled = false;
|
| 784 |
+
}}
|
| 785 |
+
}});
|
| 786 |
+
|
| 787 |
(async function load() {{
|
| 788 |
try {{
|
| 789 |
const r = await fetch(MANIFEST_EP, {{ headers:{{Accept:'application/json'}} }});
|
|
|
|
| 827 |
}};
|
| 828 |
function surfCls(label) {{ return SURF_CLASS[label] || 'unavailable'; }}
|
| 829 |
|
| 830 |
+
const SURFACE_PAGE_SIZE = 12;
|
| 831 |
+
let allSurfaces = [];
|
| 832 |
+
let activeSurfaceLabel = 'ALL';
|
| 833 |
+
let surfaceQuery = '';
|
| 834 |
+
let surfacePage = 0;
|
| 835 |
+
|
| 836 |
+
function matchingSurfaces() {{
|
| 837 |
+
const needle = surfaceQuery.toLowerCase();
|
| 838 |
+
return allSurfaces.filter(surface => {{
|
| 839 |
+
const label = surface.label || 'UNAVAILABLE';
|
| 840 |
+
const labelMatches = activeSurfaceLabel === 'ALL' || label === activeSurfaceLabel;
|
| 841 |
+
const text = [surface.id, surface.title, surface.asset, label].join(' ').toLowerCase();
|
| 842 |
+
return labelMatches && (!needle || text.includes(needle));
|
| 843 |
+
}});
|
| 844 |
+
}}
|
| 845 |
+
|
| 846 |
+
function renderSurfaceTabs(labelCounts) {{
|
| 847 |
+
const labels = ['ALL', ...Object.keys(labelCounts)];
|
| 848 |
+
const tabs = document.getElementById('surface-filters');
|
| 849 |
+
tabs.innerHTML = labels.map((label, index) => {{
|
| 850 |
+
const count = label === 'ALL' ? allSurfaces.length : (labelCounts[label] || 0);
|
| 851 |
+
return `<button type="button" class="surface-tab" role="tab" id="surface-tab-${{index}}"`
|
| 852 |
+
+ ` data-label="${{esc(label)}}" aria-selected="${{label === activeSurfaceLabel}}"`
|
| 853 |
+
+ ` aria-controls="surfaces-list" tabindex="${{label === activeSurfaceLabel ? 0 : -1}}"`
|
| 854 |
+
+ `>${{esc(label)}} ${{esc(count)}}</button>`;
|
| 855 |
+
}}).join('');
|
| 856 |
+
const tabButtons = [...tabs.querySelectorAll('[role="tab"]')];
|
| 857 |
+
tabButtons.forEach((tab, index) => {{
|
| 858 |
+
tab.addEventListener('click', () => {{
|
| 859 |
+
activeSurfaceLabel = tab.dataset.label || 'ALL';
|
| 860 |
+
surfacePage = 0;
|
| 861 |
+
renderSurfaceTabs(labelCounts);
|
| 862 |
+
renderSurfaceCatalog();
|
| 863 |
+
}});
|
| 864 |
+
tab.addEventListener('keydown', event => {{
|
| 865 |
+
let target = null;
|
| 866 |
+
if (event.key === 'ArrowRight') target = (index + 1) % tabButtons.length;
|
| 867 |
+
else if (event.key === 'ArrowLeft') target = (index - 1 + tabButtons.length) % tabButtons.length;
|
| 868 |
+
else if (event.key === 'Home') target = 0;
|
| 869 |
+
else if (event.key === 'End') target = tabButtons.length - 1;
|
| 870 |
+
if (target == null) return;
|
| 871 |
+
event.preventDefault();
|
| 872 |
+
tabButtons[target].click();
|
| 873 |
+
document.querySelectorAll('#surface-filters [role="tab"]')[target]?.focus();
|
| 874 |
+
}});
|
| 875 |
+
}});
|
| 876 |
+
}}
|
| 877 |
+
|
| 878 |
+
function renderSurfaceCatalog() {{
|
| 879 |
+
const filtered = matchingSurfaces();
|
| 880 |
+
const pageCount = Math.max(1, Math.ceil(filtered.length / SURFACE_PAGE_SIZE));
|
| 881 |
+
surfacePage = Math.min(surfacePage, pageCount - 1);
|
| 882 |
+
const start = surfacePage * SURFACE_PAGE_SIZE;
|
| 883 |
+
const visible = filtered.slice(start, start + SURFACE_PAGE_SIZE);
|
| 884 |
+
const list = document.getElementById('surfaces-list');
|
| 885 |
+
list.innerHTML = visible.length ? visible.map(surface => {{
|
| 886 |
+
const label = surface.label || 'UNAVAILABLE';
|
| 887 |
+
const target = '/holographic#' + encodeURIComponent(surface.id || '');
|
| 888 |
+
return `<a class="surface-pill" role="listitem" href="${{target}}"`
|
| 889 |
+
+ ` title="${{esc(surface.asset || '')}}" aria-label="Open ${{esc(surface.title || surface.id || 'surface')}}; ${{esc(label)}}">`
|
| 890 |
+
+ `<span class="surface-copy"><span class="sid">${{esc(surface.id || '')}}</span>`
|
| 891 |
+
+ `<span class="surface-title">${{esc(surface.title || '')}}</span></span>`
|
| 892 |
+
+ `<span class="badge ${{surfCls(label)}}">${{esc(label)}}</span></a>`;
|
| 893 |
+
}}).join('') : '<div class="surface-empty">No surface matches this exact label and search. No result fabricated.</div>';
|
| 894 |
+
|
| 895 |
+
const first = filtered.length ? start + 1 : 0;
|
| 896 |
+
const last = Math.min(start + visible.length, filtered.length);
|
| 897 |
+
document.getElementById('surface-page-status').textContent =
|
| 898 |
+
'showing ' + first + '-' + last + ' of ' + filtered.length +
|
| 899 |
+
' matching / ' + allSurfaces.length + ' total | page ' + (surfacePage + 1) + '/' + pageCount;
|
| 900 |
+
document.getElementById('surface-prev').disabled = surfacePage === 0;
|
| 901 |
+
document.getElementById('surface-next').disabled = surfacePage >= pageCount - 1 || filtered.length === 0;
|
| 902 |
+
}}
|
| 903 |
+
|
| 904 |
+
document.getElementById('surface-search').addEventListener('input', event => {{
|
| 905 |
+
surfaceQuery = event.target.value.trim();
|
| 906 |
+
surfacePage = 0;
|
| 907 |
+
renderSurfaceCatalog();
|
| 908 |
+
}});
|
| 909 |
+
document.getElementById('surface-prev').addEventListener('click', () => {{
|
| 910 |
+
if (surfacePage > 0) {{ surfacePage -= 1; renderSurfaceCatalog(); }}
|
| 911 |
+
}});
|
| 912 |
+
document.getElementById('surface-next').addEventListener('click', () => {{
|
| 913 |
+
const count = matchingSurfaces().length;
|
| 914 |
+
if ((surfacePage + 1) * SURFACE_PAGE_SIZE < count) {{ surfacePage += 1; renderSurfaceCatalog(); }}
|
| 915 |
+
}});
|
| 916 |
+
|
| 917 |
(async function loadSurfaces() {{
|
| 918 |
const statusEl = document.getElementById('surfaces-status');
|
| 919 |
try {{
|
|
|
|
| 932 |
chips.push(`<span class="chip">labels valid: <b>${{esc(String(s.labels_valid))}}</b></span>`);
|
| 933 |
document.getElementById('surfaces-rollup').innerHTML = chips.join('');
|
| 934 |
|
| 935 |
+
// retain every surface, then render a bounded honest page: id + title + label.
|
| 936 |
+
allSurfaces = surfaces;
|
| 937 |
+
renderSurfaceTabs(lc);
|
| 938 |
+
renderSurfaceCatalog();
|
|
|
|
|
|
|
|
|
|
|
|
|
| 939 |
|
| 940 |
statusEl.className = 'status-line';
|
| 941 |
statusEl.textContent = (m.ok === false)
|
|
|
|
| 943 |
: ('live · ' + esc(m.count ?? surfaces.length) + ' surfaces from ' + esc(SURFACES_EP)
|
| 944 |
+ ' · labels_valid=' + esc(String(s.labels_valid)));
|
| 945 |
}} catch (e) {{
|
| 946 |
+
allSurfaces = [];
|
| 947 |
+
renderSurfaceTabs({{}});
|
| 948 |
+
renderSurfaceCatalog();
|
| 949 |
statusEl.className = 'status-line err';
|
| 950 |
statusEl.textContent = 'surfaces unavailable: ' + e + ' (nothing fabricated — raw data at ' + SURFACES_EP + ')';
|
| 951 |
}}
|
|
|
|
| 954 |
</body></html>"""
|
| 955 |
|
| 956 |
|
| 957 |
+
def register(app, ns: str = "a11oy") -> str:
|
| 958 |
"""Mount GET /frontier (HTML) + GET /api/<ns>/v1/frontier/page-manifest (JSON).
|
| 959 |
ADDITIVE — registered before the SPA catch-all; touches no existing route."""
|
| 960 |
|
| 961 |
+
# Keep the pure manifest builders importable in bounded/offline evidence
|
| 962 |
+
# jobs where the web-serving dependency is intentionally absent.
|
| 963 |
+
from fastapi.responses import HTMLResponse, JSONResponse
|
| 964 |
+
|
| 965 |
@app.get("/frontier", include_in_schema=False)
|
| 966 |
+
async def frontier_page(): # noqa: ANN202
|
| 967 |
return HTMLResponse(_page_html(ns))
|
| 968 |
|
| 969 |
@app.get(f"/api/{ns}/v1/frontier/surfaces")
|
| 970 |
+
async def frontier_surfaces(): # noqa: ANN202
|
| 971 |
"""Machine-verifiable manifest of every 3D frontier surface.
|
| 972 |
|
| 973 |
id + title + honesty label (parsed from the surface source, verbatim) +
|
|
|
|
| 975 |
return JSONResponse(build_surfaces_manifest(ns))
|
| 976 |
|
| 977 |
@app.get(f"/api/{ns}/v1/frontier/page-manifest", include_in_schema=False)
|
| 978 |
+
async def frontier_page_manifest(): # noqa: ANN202
|
| 979 |
return JSONResponse({
|
| 980 |
"section": "Frontier",
|
| 981 |
"page": "/frontier",
|
|
|
|
| 1021 |
assert 'id="surfaces-list"' in html and 'id="surfaces-rollup"' in html, \
|
| 1022 |
"surfaces section markers missing"
|
| 1023 |
assert "loadSurfaces" in html, "surfaces client loader missing"
|
| 1024 |
+
# 8) responsive catalog retains every fetched surface in memory while rendering a
|
| 1025 |
+
# bounded, filterable page; its exact honesty labels remain the filter contract.
|
| 1026 |
+
for marker in (
|
| 1027 |
+
'id="surface-filters"', 'role="tablist"', 'id="surface-search"',
|
| 1028 |
+
'id="surface-prev"', 'id="surface-next"', 'id="surface-page-status"',
|
| 1029 |
+
"const SURFACE_PAGE_SIZE = 12", "allSurfaces = surfaces",
|
| 1030 |
+
"filtered.slice(start, start + SURFACE_PAGE_SIZE)",
|
| 1031 |
+
"'/holographic#' + encodeURIComponent", "ArrowRight", "ArrowLeft",
|
| 1032 |
+
):
|
| 1033 |
+
assert marker in html, f"responsive surface catalog marker missing: {marker}"
|
| 1034 |
+
for marker in (
|
| 1035 |
+
"--honest-banner-h", "ResizeObserver", "overflow-x:clip",
|
| 1036 |
+
"overflow-wrap:anywhere", "@media (max-width:720px)",
|
| 1037 |
+
"@media (max-width:420px)", "prefers-reduced-motion:reduce",
|
| 1038 |
+
):
|
| 1039 |
+
assert marker in html, f"responsive shell marker missing: {marker}"
|
| 1040 |
+
# 9) the Evidence Brain only displays live reads and measured client RTT; it
|
| 1041 |
+
# never promises a latency target or invents an ingestion uplift.
|
| 1042 |
+
for marker in (
|
| 1043 |
+
"/api/a11oy/v1/brain/stats",
|
| 1044 |
+
"/api/a11oy/v1/brain/health/corpus-sources",
|
| 1045 |
+
"/api/a11oy/v1/brain/ask",
|
| 1046 |
+
'id="brain-query-form"', "performance.now()", "cited_node_ids",
|
| 1047 |
+
"NOT MEASURED", 'href="/formulas"',
|
| 1048 |
+
):
|
| 1049 |
+
assert marker in html, f"Evidence Brain marker missing: {marker}"
|
| 1050 |
+
assert "answers in 2 seconds" not in html.lower(), "unmeasured latency promise found"
|
| 1051 |
+
|
| 1052 |
+
# 10) the manifest builder parses the live registry honestly
|
| 1053 |
man = build_surfaces_manifest("a11oy")
|
| 1054 |
assert man["ok"] is True, f"surfaces manifest not ok: {man.get('error')}"
|
| 1055 |
assert man["count"] == len(man["surfaces"]) and man["count"] > 0, "surface count mismatch"
|
|
@@ -37,17 +37,31 @@ async def _a11oy_frontier_health(request: Request):
|
|
| 37 |
|
| 38 |
async def _a11oy_frontier_version(request: Request):
|
| 39 |
import os as _os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
return _FJSON({
|
| 41 |
-
|
| 42 |
-
"git_sha": _os.getenv("SZL_GIT_SHA"
|
| 43 |
-
"hf_space_sha": _os.getenv("SZL_HF_SHA"
|
| 44 |
-
"build_time": _os.getenv("SZL_BUILD_TIME"
|
| 45 |
-
"release_url": "https://github.com/szl-holdings/a11oy/releases/tag/v1.0.0",
|
| 46 |
"doctrine": _DOCTRINE, "kernel_commit": _KERNEL,
|
| 47 |
"p6_status": "SIGNED_OFF", "p6_grader_score": "14/14",
|
| 48 |
"verify": {
|
| 49 |
-
"
|
| 50 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
},
|
| 52 |
# ADDITIVE (waveL Dev2): machine-readable release record of the waves'
|
| 53 |
# shipped capabilities, HONEST labels. Canonical human record: CHANGELOG.md.
|
|
|
|
| 37 |
|
| 38 |
async def _a11oy_frontier_version(request: Request):
|
| 39 |
import os as _os
|
| 40 |
+
from szl_release_identity import release_identity as _release_identity
|
| 41 |
+
|
| 42 |
+
identity = _release_identity()
|
| 43 |
+
release_tag = identity.get("release_tag")
|
| 44 |
+
release_assets_ready = bool(release_tag)
|
| 45 |
return _FJSON({
|
| 46 |
+
**identity,
|
| 47 |
+
"git_sha": _os.getenv("SZL_GIT_SHA") or "UNKNOWN",
|
| 48 |
+
"hf_space_sha": _os.getenv("SZL_HF_SHA") or "UNKNOWN",
|
| 49 |
+
"build_time": _os.getenv("SZL_BUILD_TIME") or "UNKNOWN",
|
|
|
|
| 50 |
"doctrine": _DOCTRINE, "kernel_commit": _KERNEL,
|
| 51 |
"p6_status": "SIGNED_OFF", "p6_grader_score": "14/14",
|
| 52 |
"verify": {
|
| 53 |
+
"release_assets_status": "CONFIGURED_UNVERIFIED" if release_assets_ready else "PENDING_RELEASE",
|
| 54 |
+
"cosign": (
|
| 55 |
+
f"cosign verify ghcr.io/szl-holdings/a11oy:{release_tag} --certificate-identity-regexp=szl-holdings"
|
| 56 |
+
if release_assets_ready
|
| 57 |
+
else None
|
| 58 |
+
),
|
| 59 |
+
"sbom": (
|
| 60 |
+
f"https://github.com/szl-holdings/a11oy/releases/download/{release_tag}/a11oy-sbom.cdx.json"
|
| 61 |
+
if release_assets_ready
|
| 62 |
+
else None
|
| 63 |
+
),
|
| 64 |
+
"honest": "https://a-11-oy.com/api/a11oy/v1/honest",
|
| 65 |
},
|
| 66 |
# ADDITIVE (waveL Dev2): machine-readable release record of the waves'
|
| 67 |
# shipped capabilities, HONEST labels. Canonical human record: CHANGELOG.md.
|
|
@@ -159,11 +159,11 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 159 |
base = f"/api/{ns}/v1/assets"
|
| 160 |
|
| 161 |
@app.get(base + "/manifest")
|
| 162 |
-
async def _assets_manifest()
|
| 163 |
return JSONResponse(manifest())
|
| 164 |
|
| 165 |
@app.get(base + "/{key}")
|
| 166 |
-
async def _asset_one(key: str)
|
| 167 |
return JSONResponse(asset_status(key))
|
| 168 |
|
| 169 |
new = app.router.routes[n_before:]
|
|
|
|
| 159 |
base = f"/api/{ns}/v1/assets"
|
| 160 |
|
| 161 |
@app.get(base + "/manifest")
|
| 162 |
+
async def _assets_manifest(): # noqa: ANN202
|
| 163 |
return JSONResponse(manifest())
|
| 164 |
|
| 165 |
@app.get(base + "/{key}")
|
| 166 |
+
async def _asset_one(key: str): # noqa: ANN202
|
| 167 |
return JSONResponse(asset_status(key))
|
| 168 |
|
| 169 |
new = app.router.routes[n_before:]
|
|
@@ -1,12 +1,12 @@
|
|
| 1 |
"""
|
| 2 |
a11oy_nemo_core.py — SZL-NEMO CORE (Lane I1).
|
| 3 |
|
| 4 |
-
SZL-Nemo is
|
| 5 |
-
|
| 6 |
payload and on the tab, is:
|
| 7 |
|
| 8 |
-
"SZL-Nemo — built on
|
| 9 |
-
governed
|
| 10 |
|
| 11 |
NEVER claim: from-scratch training, 550B parameters, local Nemotron-Ultra, or a
|
| 12 |
certification. We did NOT train a foundation model. OUR contribution is the
|
|
@@ -62,6 +62,9 @@ import math
|
|
| 62 |
import os
|
| 63 |
import threading
|
| 64 |
import time
|
|
|
|
|
|
|
|
|
|
| 65 |
from datetime import datetime, timezone
|
| 66 |
|
| 67 |
# ---------------------------------------------------------------------------
|
|
@@ -69,38 +72,46 @@ from datetime import datetime, timezone
|
|
| 69 |
# governance/routing/self-improvement layer — NOT a from-scratch foundation model.
|
| 70 |
# ---------------------------------------------------------------------------
|
| 71 |
NEMO_NAME = "SZL-Nemo"
|
| 72 |
-
NEMO_VERSION = "0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
NEMO_ARTIFACT = {
|
| 74 |
"repo_id": "SZLHOLDINGS/szl-nemo",
|
| 75 |
"url": "https://huggingface.co/SZLHOLDINGS/szl-nemo",
|
| 76 |
"kind": "configuration-recipe",
|
| 77 |
"weights_present": False,
|
| 78 |
-
"training_state": "
|
|
|
|
|
|
|
| 79 |
"honesty": (
|
| 80 |
"The Hub artifact currently contains a model card and Modelfile recipe, "
|
| 81 |
"not SZL-trained weights. It must not be described as a fine-tuned model."
|
| 82 |
),
|
| 83 |
}
|
| 84 |
|
| 85 |
-
#
|
| 86 |
-
#
|
| 87 |
-
# is offered as an alternative. NEVER imply from-scratch / 550B.
|
| 88 |
NEMO_BASE = {
|
| 89 |
-
"default_base": "
|
| 90 |
-
"
|
| 91 |
-
"
|
| 92 |
-
"
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
],
|
| 98 |
"honest_framing": (
|
| 99 |
-
"SZL-Nemo is
|
| 100 |
-
"NOT
|
| 101 |
-
"
|
| 102 |
-
"
|
| 103 |
-
"
|
| 104 |
"never_claim": ["from-scratch training", "550B parameters", "local Nemotron-Ultra",
|
| 105 |
"any certification (FedRAMP/IronBank/CMMC/ATO)"],
|
| 106 |
}
|
|
@@ -158,13 +169,13 @@ DOCTRINE = {
|
|
| 158 |
# (Leviathan et al. 2022 / Dev C #2). We mark the acceptance rate ILLUSTRATIVE
|
| 159 |
# until the box emits real accept/draft counters → then it flips to MEASURED.
|
| 160 |
MTP_DEFAULT = {
|
| 161 |
-
"enabled_default":
|
| 162 |
-
"draft_model":
|
| 163 |
-
"target_model":
|
| 164 |
"num_speculative_tokens_k": 4,
|
| 165 |
"acceptance_rate_alpha": 0.8, # ILLUSTRATIVE until box emits accept/draft counters
|
| 166 |
"label_when_unmeasured": "ROADMAP",
|
| 167 |
-
"source": "speculative decoding (Leviathan et al. arXiv:2211.17192)
|
| 168 |
}
|
| 169 |
|
| 170 |
_LOCK = threading.RLock()
|
|
@@ -603,12 +614,149 @@ def mtp_view():
|
|
| 603 |
|
| 604 |
|
| 605 |
# ---------------------------------------------------------------------------
|
| 606 |
-
#
|
| 607 |
-
#
|
| 608 |
-
#
|
| 609 |
-
# returns the GOVERNED PLAN + signed receipt, honestly labelled SKELETON.
|
| 610 |
# ---------------------------------------------------------------------------
|
| 611 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 612 |
route = govern_route(query, top_k=top_k, sign_fn=None) # inner decision (re-signed below)
|
| 613 |
primary = route["experts"][0] if route["experts"] else None
|
| 614 |
serving = (primary or {}).get("serving_crossover", {})
|
|
@@ -621,18 +769,37 @@ def infer(query: str, top_k: int = 2, sign_fn=None):
|
|
| 621 |
"routed_experts": route["experts_selected"],
|
| 622 |
"primary_expert": (primary or {}).get("expert_id"),
|
| 623 |
"serving_tier": tier_choice,
|
| 624 |
-
"serving_where": "sovereign-local
|
| 625 |
else "cloud-NIM-frontier (Nemotron Ultra)",
|
| 626 |
"mtp": mtp_view(),
|
| 627 |
"overall_lambda_advisory": route["overall_lambda_advisory"],
|
|
|
|
|
|
|
| 628 |
"skeleton_note": (
|
| 629 |
-
"
|
| 630 |
-
"
|
| 631 |
-
"sovereign-local 2-GPU tier (ROADMAP→Forge) or the cloud-NIM tier. No "
|
| 632 |
-
"model output is fabricated."),
|
| 633 |
"tiers": tiers_view(),
|
| 634 |
"ts_utc": datetime.now(timezone.utc).isoformat(),
|
| 635 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 636 |
# If the routed primary expert is CODE, this turn is on the code-emission
|
| 637 |
# path: gate the intended diff through R1's restraint ladder and attach the
|
| 638 |
# chosen rung + signed restraint receipt (honest PENDING if R1 not live yet).
|
|
@@ -656,8 +823,8 @@ def nemo_code(query: str, intent: str | None = None, intensity: str = "full",
|
|
| 656 |
"""A governed code-emission turn. `intent` is the natural-language description
|
| 657 |
of the diff SZL-Nemo is about to write (defaults to the query). We route it
|
| 658 |
through restraint BEFORE emitting, surface the rung + ceilings + lines-saved,
|
| 659 |
-
and sign the combined decision.
|
| 660 |
-
|
| 661 |
the GOVERNED, restraint-gated code PLAN + a signed receipt, honestly labelled."""
|
| 662 |
task = (intent or query or "").strip()
|
| 663 |
route = govern_route(query, top_k=2, sign_fn=None)
|
|
@@ -676,9 +843,8 @@ def nemo_code(query: str, intent: str | None = None, intensity: str = "full",
|
|
| 676 |
"overall_lambda_advisory": route["overall_lambda_advisory"],
|
| 677 |
"skeleton_note": (
|
| 678 |
"GOVERNED CODE PLAN — the intended diff is routed through a11oy "
|
| 679 |
-
"Restraint (R1) BEFORE any code is emitted.
|
| 680 |
-
"
|
| 681 |
-
"tier (ROADMAP→Forge) or cloud-NIM tier. No code is fabricated here."),
|
| 682 |
"ponytail": _PONYTAIL,
|
| 683 |
"doctrine": DOCTRINE,
|
| 684 |
"ts_utc": datetime.now(timezone.utc).isoformat(),
|
|
@@ -695,56 +861,22 @@ def nemo_code(query: str, intent: str | None = None, intensity: str = "full",
|
|
| 695 |
# sovereign:true ONLY from the live gpu_reachable probe (Dev C). cloud = false.
|
| 696 |
# ---------------------------------------------------------------------------
|
| 697 |
def tiers_view():
|
| 698 |
-
|
| 699 |
-
|
| 700 |
-
base_url = None
|
| 701 |
-
probe_note = "szl_energy_sovereign unavailable in-process; honest default not-sovereign."
|
| 702 |
-
if en is not None and hasattr(en, "_sovereign_state"):
|
| 703 |
-
try:
|
| 704 |
-
st = en._sovereign_state()
|
| 705 |
-
sovereign = bool(en._gpu_reachable(st)) if hasattr(en, "_gpu_reachable") else False
|
| 706 |
-
base_url = st.get("base_url")
|
| 707 |
-
probe_note = st.get("honest_note") or (
|
| 708 |
-
"live gpu_reachable probe: sovereign=%s" % sovereign)
|
| 709 |
-
except Exception as e:
|
| 710 |
-
probe_note = "probe error (%s); honest default not-sovereign." % type(e).__name__
|
| 711 |
-
# Model-aware honesty: the node being reachable (the sovereign brain, e.g.
|
| 712 |
-
# qwen2.5-coder:7b today) does NOT make the SZL-Nemo Qwen3-32B / 2-GPU tier live.
|
| 713 |
-
# Labelling a 32B that is served NOWHERE as MEASURED would be the half-state. This
|
| 714 |
-
# tier is MEASURED/sovereign ONLY when a 32B base is genuinely served; otherwise it
|
| 715 |
-
# is ROADMAP while honestly naming what IS served on the reachable node.
|
| 716 |
-
_served_model = (os.environ.get("SZL_LOCAL_LLM_MODEL")
|
| 717 |
-
or os.environ.get("A11OY_LOCAL_LLM_MODEL") or "").strip()
|
| 718 |
-
_base_served = bool(sovereign) and ("32b" in _served_model.lower())
|
| 719 |
-
if _base_served:
|
| 720 |
-
_local_honesty = ("MEASURED — a live probe confirms the named 32B base is "
|
| 721 |
-
"served on our GPU. NEVER claim local Nemotron-Ultra.")
|
| 722 |
-
elif sovereign:
|
| 723 |
-
_local_honesty = ("Node reachable now serving %r (the sovereign brain); the "
|
| 724 |
-
"SZL-Nemo Qwen3-32B / 2-GPU serve is ROADMAP (founder-gated: "
|
| 725 |
-
"one 7B-class GPU is reachable, no 32B / no vLLM TP=2 / 2nd "
|
| 726 |
-
"card asleep) — see FORGE_SZL_NEMO.md. NEVER claim local "
|
| 727 |
-
"Nemotron-Ultra." % (_served_model or "a small local model"))
|
| 728 |
-
else:
|
| 729 |
-
_local_honesty = ("Not reachable; honest ROADMAP. sovereign:true for this tier "
|
| 730 |
-
"ONLY when a live probe confirms the 32B base is served on our "
|
| 731 |
-
"GPU. NEVER claim local Nemotron-Ultra.")
|
| 732 |
local_tier = {
|
| 733 |
"tier_id": "sovereign-local",
|
| 734 |
-
"title": "Sovereign-Local
|
| 735 |
"where": "gpu",
|
| 736 |
-
"sovereign":
|
| 737 |
-
"gpu_reachable":
|
| 738 |
-
"node_serving_now": (
|
| 739 |
"base_model": NEMO_BASE["default_base"] + " (open base, " +
|
| 740 |
NEMO_BASE["default_base_license"] + ")",
|
| 741 |
-
"plan":
|
| 742 |
-
|
| 743 |
-
|
| 744 |
-
"
|
| 745 |
-
"
|
| 746 |
-
"label": "MEASURED" if _base_served else "ROADMAP",
|
| 747 |
-
"honesty": _local_honesty,
|
| 748 |
}
|
| 749 |
cloud_tier = {
|
| 750 |
"tier_id": "cloud-NIM-frontier",
|
|
@@ -767,8 +899,8 @@ def tiers_view():
|
|
| 767 |
"schema": "szl.nemo.tiers/v1",
|
| 768 |
"model": NEMO_NAME,
|
| 769 |
"tiers": [local_tier, cloud_tier],
|
| 770 |
-
"future": ("
|
| 771 |
-
"
|
| 772 |
"doctrine": ("sovereign:true only via live probe; measured > datasheet; "
|
| 773 |
"0 CDN; signed receipts; never commit a key."),
|
| 774 |
"ts_utc": datetime.now(timezone.utc).isoformat(),
|
|
@@ -938,20 +1070,21 @@ def model_card():
|
|
| 938 |
return {
|
| 939 |
"schema": "szl.nemo.model_card/v1",
|
| 940 |
"name": NEMO_NAME, "version": NEMO_VERSION,
|
| 941 |
-
"one_liner": ("SZL-Nemo — a
|
| 942 |
-
"built
|
| 943 |
"base": NEMO_BASE,
|
| 944 |
"hub_artifact": NEMO_ARTIFACT,
|
| 945 |
"what_is_ours": [
|
| 946 |
"Governed-MoE DOMAIN-EXPERT router (Λ-governed, signed every selection) — the differentiator.",
|
| 947 |
-
"
|
| 948 |
"Reflexion + Voyager + τ-bench self-improvement loop that SIGNS the measured delta.",
|
| 949 |
-
"Tiered
|
| 950 |
"Tamper-evident DSSE ECDSA-P256 signed receipts on every governed step.",
|
| 951 |
],
|
| 952 |
"what_is_NOT_ours": [
|
| 953 |
-
"The base weights (
|
| 954 |
"We did NOT train a foundation model from scratch.",
|
|
|
|
| 955 |
"There is NO 550B SZL model and NO local Nemotron-Ultra (cloud tier only).",
|
| 956 |
],
|
| 957 |
"experts": [{"id": e["id"], "title": e["title"], "desc": e["desc"]} for e in NEMO_EXPERTS],
|
|
@@ -960,8 +1093,11 @@ def model_card():
|
|
| 960 |
"tiers": tiers_view(),
|
| 961 |
"doctrine": DOCTRINE,
|
| 962 |
"never_claim": NEMO_BASE["never_claim"],
|
|
|
|
| 963 |
"sources": {
|
| 964 |
-
"
|
|
|
|
|
|
|
| 965 |
"speculative_decoding": "https://arxiv.org/abs/2211.17192",
|
| 966 |
"reflexion": "https://arxiv.org/abs/2303.11366",
|
| 967 |
"voyager": "https://arxiv.org/abs/2305.16291",
|
|
@@ -1021,7 +1157,10 @@ def register(app, ns: str = "a11oy", sign_fn=None, verify_fn=None,
|
|
| 1021 |
if not q:
|
| 1022 |
return JSONResponse({"error": "missing 'query'"}, status_code=400)
|
| 1023 |
top_k = int(d.get("top_k", 2))
|
| 1024 |
-
|
|
|
|
|
|
|
|
|
|
| 1025 |
|
| 1026 |
async def _code_ep(request):
|
| 1027 |
if request.method == "POST":
|
|
@@ -1060,6 +1199,7 @@ def register(app, ns: str = "a11oy", sign_fn=None, verify_fn=None,
|
|
| 1060 |
async def _diag_ep(request):
|
| 1061 |
return JSONResponse({
|
| 1062 |
"status": "ok", "model": NEMO_NAME, "version": NEMO_VERSION,
|
|
|
|
| 1063 |
"signer_present": sign_fn is not None,
|
| 1064 |
"signer_label": signer_label,
|
| 1065 |
"reuse": {
|
|
|
|
| 1 |
"""
|
| 2 |
a11oy_nemo_core.py — SZL-NEMO CORE (Lane I1).
|
| 3 |
|
| 4 |
+
SZL-Nemo is an SZL-governed recipe and orchestration runtime built on NVIDIA
|
| 5 |
+
Nemotron 3 Nano 4B. The HONEST framing, repeated in every
|
| 6 |
payload and on the tab, is:
|
| 7 |
|
| 8 |
+
"SZL-Nemo — built on NVIDIA Nemotron 3 Nano 4B under its upstream license,
|
| 9 |
+
governed and served on SZL-controlled infrastructure when verified."
|
| 10 |
|
| 11 |
NEVER claim: from-scratch training, 550B parameters, local Nemotron-Ultra, or a
|
| 12 |
certification. We did NOT train a foundation model. OUR contribution is the
|
|
|
|
| 62 |
import os
|
| 63 |
import threading
|
| 64 |
import time
|
| 65 |
+
import urllib.error
|
| 66 |
+
import urllib.parse
|
| 67 |
+
import urllib.request
|
| 68 |
from datetime import datetime, timezone
|
| 69 |
|
| 70 |
# ---------------------------------------------------------------------------
|
|
|
|
| 72 |
# governance/routing/self-improvement layer — NOT a from-scratch foundation model.
|
| 73 |
# ---------------------------------------------------------------------------
|
| 74 |
NEMO_NAME = "SZL-Nemo"
|
| 75 |
+
NEMO_VERSION = "0.2.0-runtime-bound"
|
| 76 |
+
NEMO_UPSTREAM_OLLAMA_MODEL = "nemotron-3-nano:4b"
|
| 77 |
+
NEMO_SERVED_MODEL = os.environ.get("SZL_NEMO_MODEL", "szl-nemo:latest").strip()
|
| 78 |
+
NEMO_OLLAMA_URL = os.environ.get(
|
| 79 |
+
"SZL_NEMO_OLLAMA_URL", "http://127.0.0.1:11436"
|
| 80 |
+
).strip().rstrip("/")
|
| 81 |
+
NEMO_EXPECTED_REGISTRY_MANIFEST_SHA256 = (
|
| 82 |
+
"6cc467f054393a55e98a74098abde0c762ffb6d1d8cd64becf30458f38886197"
|
| 83 |
+
)
|
| 84 |
NEMO_ARTIFACT = {
|
| 85 |
"repo_id": "SZLHOLDINGS/szl-nemo",
|
| 86 |
"url": "https://huggingface.co/SZLHOLDINGS/szl-nemo",
|
| 87 |
"kind": "configuration-recipe",
|
| 88 |
"weights_present": False,
|
| 89 |
+
"training_state": "NOT_FINE_TUNED",
|
| 90 |
+
"upstream_ollama_model": NEMO_UPSTREAM_OLLAMA_MODEL,
|
| 91 |
+
"expected_registry_manifest_sha256": NEMO_EXPECTED_REGISTRY_MANIFEST_SHA256,
|
| 92 |
"honesty": (
|
| 93 |
"The Hub artifact currently contains a model card and Modelfile recipe, "
|
| 94 |
"not SZL-trained weights. It must not be described as a fine-tuned model."
|
| 95 |
),
|
| 96 |
}
|
| 97 |
|
| 98 |
+
# Exact public recipe: NVIDIA Nemotron 3 Nano 4B through a content-bound Ollama
|
| 99 |
+
# registry manifest. The prompt and governed runtime are SZL work; the weights are not.
|
|
|
|
| 100 |
NEMO_BASE = {
|
| 101 |
+
"default_base": "NVIDIA Nemotron 3 Nano 4B",
|
| 102 |
+
"default_base_tag": NEMO_UPSTREAM_OLLAMA_MODEL,
|
| 103 |
+
"default_base_license": "NVIDIA Nemotron Open Model License",
|
| 104 |
+
"default_base_url": "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Nano-4B-BF16",
|
| 105 |
+
"gguf_url": "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Nano-4B-GGUF",
|
| 106 |
+
"license_url": "https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Nano-4B-BF16/blob/main/LICENSE",
|
| 107 |
+
"registry_manifest_sha256": NEMO_EXPECTED_REGISTRY_MANIFEST_SHA256,
|
| 108 |
+
"alternatives": [],
|
|
|
|
| 109 |
"honest_framing": (
|
| 110 |
+
"SZL-Nemo is a governed Ollama recipe built ON NVIDIA Nemotron 3 Nano 4B. "
|
| 111 |
+
"SZL did NOT fine-tune or train these weights. OUR contribution is the "
|
| 112 |
+
"doctrine prompt, governed domain router, runtime identity binding, and "
|
| 113 |
+
"signed receipts. The exact upstream registry manifest must match before "
|
| 114 |
+
"the local tier can report READY."),
|
| 115 |
"never_claim": ["from-scratch training", "550B parameters", "local Nemotron-Ultra",
|
| 116 |
"any certification (FedRAMP/IronBank/CMMC/ATO)"],
|
| 117 |
}
|
|
|
|
| 169 |
# (Leviathan et al. 2022 / Dev C #2). We mark the acceptance rate ILLUSTRATIVE
|
| 170 |
# until the box emits real accept/draft counters → then it flips to MEASURED.
|
| 171 |
MTP_DEFAULT = {
|
| 172 |
+
"enabled_default": False,
|
| 173 |
+
"draft_model": None,
|
| 174 |
+
"target_model": NEMO_UPSTREAM_OLLAMA_MODEL,
|
| 175 |
"num_speculative_tokens_k": 4,
|
| 176 |
"acceptance_rate_alpha": 0.8, # ILLUSTRATIVE until box emits accept/draft counters
|
| 177 |
"label_when_unmeasured": "ROADMAP",
|
| 178 |
+
"source": "speculative decoding (Leviathan et al. arXiv:2211.17192); not enabled on the verified Ollama path",
|
| 179 |
}
|
| 180 |
|
| 181 |
_LOCK = threading.RLock()
|
|
|
|
| 614 |
|
| 615 |
|
| 616 |
# ---------------------------------------------------------------------------
|
| 617 |
+
# LOCAL RUNTIME — fail closed to a loopback-only Ollama service. Readiness binds
|
| 618 |
+
# both the mutable upstream tag and the derived SZL recipe tag. A reachable port
|
| 619 |
+
# alone is not enough and a model's prose is never accepted as identity evidence.
|
|
|
|
| 620 |
# ---------------------------------------------------------------------------
|
| 621 |
+
def _ollama_base_url() -> str:
|
| 622 |
+
parsed = urllib.parse.urlsplit(NEMO_OLLAMA_URL)
|
| 623 |
+
if parsed.scheme != "http" or parsed.username or parsed.password:
|
| 624 |
+
raise ValueError("SZL-Nemo requires a credential-free loopback HTTP URL")
|
| 625 |
+
if parsed.hostname not in {"127.0.0.1", "localhost", "::1"}:
|
| 626 |
+
raise ValueError("SZL-Nemo refuses non-loopback Ollama endpoints")
|
| 627 |
+
if parsed.path not in {"", "/"} or parsed.query or parsed.fragment:
|
| 628 |
+
raise ValueError("SZL-Nemo Ollama URL must not contain path/query/fragment")
|
| 629 |
+
return NEMO_OLLAMA_URL
|
| 630 |
+
|
| 631 |
+
|
| 632 |
+
def _ollama_json(path: str, payload=None, timeout_s: float = 8.0):
|
| 633 |
+
base = _ollama_base_url()
|
| 634 |
+
body = None
|
| 635 |
+
headers = {"Accept": "application/json"}
|
| 636 |
+
method = "GET"
|
| 637 |
+
if payload is not None:
|
| 638 |
+
body = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
| 639 |
+
headers["Content-Type"] = "application/json"
|
| 640 |
+
method = "POST"
|
| 641 |
+
req = urllib.request.Request(base + path, data=body, method=method, headers=headers)
|
| 642 |
+
with urllib.request.urlopen(req, timeout=timeout_s) as response:
|
| 643 |
+
if response.status != 200:
|
| 644 |
+
raise RuntimeError("Ollama returned HTTP %s" % response.status)
|
| 645 |
+
raw = response.read(8 * 1024 * 1024 + 1)
|
| 646 |
+
if len(raw) > 8 * 1024 * 1024:
|
| 647 |
+
raise RuntimeError("Ollama response exceeded the bounded receipt limit")
|
| 648 |
+
value = json.loads(raw.decode("utf-8"))
|
| 649 |
+
if not isinstance(value, dict):
|
| 650 |
+
raise RuntimeError("Ollama returned a non-object response")
|
| 651 |
+
return value
|
| 652 |
+
|
| 653 |
+
|
| 654 |
+
def _normal_model_tag(value: str) -> str:
|
| 655 |
+
value = (value or "").strip()
|
| 656 |
+
return value if ":" in value else value + ":latest"
|
| 657 |
+
|
| 658 |
+
|
| 659 |
+
def nemo_runtime_status() -> dict:
|
| 660 |
+
expected = NEMO_EXPECTED_REGISTRY_MANIFEST_SHA256.lower()
|
| 661 |
+
try:
|
| 662 |
+
data = _ollama_json("/api/tags")
|
| 663 |
+
observed = {}
|
| 664 |
+
for item in data.get("models") or []:
|
| 665 |
+
if not isinstance(item, dict):
|
| 666 |
+
continue
|
| 667 |
+
name = _normal_model_tag(str(item.get("name") or item.get("model") or ""))
|
| 668 |
+
if name:
|
| 669 |
+
observed[name] = str(item.get("digest") or "").lower()
|
| 670 |
+
upstream = _normal_model_tag(NEMO_UPSTREAM_OLLAMA_MODEL)
|
| 671 |
+
served = _normal_model_tag(NEMO_SERVED_MODEL)
|
| 672 |
+
upstream_digest = observed.get(upstream)
|
| 673 |
+
served_digest = observed.get(served)
|
| 674 |
+
manifest_match = upstream_digest == expected
|
| 675 |
+
ready = bool(manifest_match and served_digest)
|
| 676 |
+
return {
|
| 677 |
+
"schema": "szl.nemo.runtime-status/v1",
|
| 678 |
+
"state": "READY" if ready else "UNAVAILABLE",
|
| 679 |
+
"transport": "OLLAMA_LOOPBACK",
|
| 680 |
+
"endpoint": _ollama_base_url(),
|
| 681 |
+
"served_model": served,
|
| 682 |
+
"served_model_digest": served_digest,
|
| 683 |
+
"upstream_model": upstream,
|
| 684 |
+
"upstream_registry_manifest_sha256": upstream_digest,
|
| 685 |
+
"expected_registry_manifest_sha256": expected,
|
| 686 |
+
"upstream_manifest_match": manifest_match,
|
| 687 |
+
"weights_origin": "NVIDIA",
|
| 688 |
+
"szl_fine_tuned": False,
|
| 689 |
+
"training_state": "NOT_FINE_TUNED",
|
| 690 |
+
"honesty": (
|
| 691 |
+
"Runtime and immutable upstream identity are verified; model quality "
|
| 692 |
+
"remains unestablished." if ready else
|
| 693 |
+
"Required exact upstream and derived recipe tags are not both verified."
|
| 694 |
+
),
|
| 695 |
+
}
|
| 696 |
+
except Exception as exc:
|
| 697 |
+
return {
|
| 698 |
+
"schema": "szl.nemo.runtime-status/v1",
|
| 699 |
+
"state": "UNAVAILABLE",
|
| 700 |
+
"transport": "OLLAMA_LOOPBACK",
|
| 701 |
+
"endpoint": NEMO_OLLAMA_URL,
|
| 702 |
+
"served_model": _normal_model_tag(NEMO_SERVED_MODEL),
|
| 703 |
+
"served_model_digest": None,
|
| 704 |
+
"upstream_model": _normal_model_tag(NEMO_UPSTREAM_OLLAMA_MODEL),
|
| 705 |
+
"upstream_registry_manifest_sha256": None,
|
| 706 |
+
"expected_registry_manifest_sha256": expected,
|
| 707 |
+
"upstream_manifest_match": False,
|
| 708 |
+
"weights_origin": "NVIDIA",
|
| 709 |
+
"szl_fine_tuned": False,
|
| 710 |
+
"training_state": "NOT_FINE_TUNED",
|
| 711 |
+
"error_type": type(exc).__name__,
|
| 712 |
+
"honesty": "Local runtime is unavailable; no model output is fabricated.",
|
| 713 |
+
}
|
| 714 |
+
|
| 715 |
+
|
| 716 |
+
def _live_nemo_generate(query: str, runtime: dict) -> dict:
|
| 717 |
+
if runtime.get("state") != "READY":
|
| 718 |
+
raise RuntimeError("SZL-Nemo runtime identity is not READY")
|
| 719 |
+
started = time.perf_counter_ns()
|
| 720 |
+
result = _ollama_json("/api/generate", {
|
| 721 |
+
"model": runtime["served_model"],
|
| 722 |
+
"prompt": query,
|
| 723 |
+
"stream": False,
|
| 724 |
+
# Nemotron is a reasoning model. Ollama otherwise places its bounded
|
| 725 |
+
# generation in the separate `thinking` field and may exhaust the token
|
| 726 |
+
# budget before emitting `response`. This public inference contract
|
| 727 |
+
# needs an answer, not a hidden reasoning trace, so disable thinking
|
| 728 |
+
# explicitly and continue to fail closed on an empty response.
|
| 729 |
+
"think": False,
|
| 730 |
+
"keep_alive": "5m",
|
| 731 |
+
"options": {"temperature": 0.2, "num_predict": 384},
|
| 732 |
+
}, timeout_s=180.0)
|
| 733 |
+
answer = result.get("response")
|
| 734 |
+
if not isinstance(answer, str) or not answer.strip():
|
| 735 |
+
raise RuntimeError("Ollama returned no answer text")
|
| 736 |
+
observed_model = _normal_model_tag(str(result.get("model") or ""))
|
| 737 |
+
if observed_model != runtime["served_model"]:
|
| 738 |
+
raise RuntimeError("served model identity mismatch")
|
| 739 |
+
return {
|
| 740 |
+
"state": "ANSWERED_UNVERIFIED",
|
| 741 |
+
"answer": answer.strip(),
|
| 742 |
+
"answer_sha256": hashlib.sha256(answer.strip().encode("utf-8")).hexdigest(),
|
| 743 |
+
"observed_model": observed_model,
|
| 744 |
+
"served_model_digest": runtime["served_model_digest"],
|
| 745 |
+
"upstream_registry_manifest_sha256": runtime["upstream_registry_manifest_sha256"],
|
| 746 |
+
"latency_ms": round((time.perf_counter_ns() - started) / 1_000_000, 3),
|
| 747 |
+
"eval_count": result.get("eval_count"),
|
| 748 |
+
"eval_duration_ns": result.get("eval_duration"),
|
| 749 |
+
"load_duration_ns": result.get("load_duration"),
|
| 750 |
+
"quality_state": "UNVERIFIED_MODEL_OUTPUT",
|
| 751 |
+
"training_state": "NOT_FINE_TUNED",
|
| 752 |
+
}
|
| 753 |
+
|
| 754 |
+
|
| 755 |
+
# ---------------------------------------------------------------------------
|
| 756 |
+
# INFER — plan by default for library callers; the HTTP endpoint explicitly asks
|
| 757 |
+
# for execution. A failed runtime stays UNAVAILABLE and never turns into demo text.
|
| 758 |
+
# ---------------------------------------------------------------------------
|
| 759 |
+
def infer(query: str, top_k: int = 2, sign_fn=None, execute: bool = False):
|
| 760 |
route = govern_route(query, top_k=top_k, sign_fn=None) # inner decision (re-signed below)
|
| 761 |
primary = route["experts"][0] if route["experts"] else None
|
| 762 |
serving = (primary or {}).get("serving_crossover", {})
|
|
|
|
| 769 |
"routed_experts": route["experts_selected"],
|
| 770 |
"primary_expert": (primary or {}).get("expert_id"),
|
| 771 |
"serving_tier": tier_choice,
|
| 772 |
+
"serving_where": "sovereign-local Ollama" if tier_choice == "small/local"
|
| 773 |
else "cloud-NIM-frontier (Nemotron Ultra)",
|
| 774 |
"mtp": mtp_view(),
|
| 775 |
"overall_lambda_advisory": route["overall_lambda_advisory"],
|
| 776 |
+
"execution_requested": bool(execute),
|
| 777 |
+
"runtime": nemo_runtime_status(),
|
| 778 |
"skeleton_note": (
|
| 779 |
+
"Plan-only library call; set execute=true through the HTTP endpoint for "
|
| 780 |
+
"a fail-closed local generation. No model output is fabricated."),
|
|
|
|
|
|
|
| 781 |
"tiers": tiers_view(),
|
| 782 |
"ts_utc": datetime.now(timezone.utc).isoformat(),
|
| 783 |
}
|
| 784 |
+
if execute:
|
| 785 |
+
try:
|
| 786 |
+
plan["generation"] = _live_nemo_generate(query, plan["runtime"])
|
| 787 |
+
plan["execution_state"] = "ANSWERED_UNVERIFIED"
|
| 788 |
+
plan["skeleton_note"] = (
|
| 789 |
+
"A real local model generated this output. Runtime identity and hashes "
|
| 790 |
+
"are measured; correctness and fine-tuning quality are not established."
|
| 791 |
+
)
|
| 792 |
+
except Exception as exc:
|
| 793 |
+
plan["generation"] = None
|
| 794 |
+
plan["execution_state"] = "UNAVAILABLE"
|
| 795 |
+
plan["runtime_error_type"] = type(exc).__name__
|
| 796 |
+
plan["skeleton_note"] = (
|
| 797 |
+
"Execution was requested but the exact runtime/model identity did not "
|
| 798 |
+
"complete. No fallback or demo answer was fabricated."
|
| 799 |
+
)
|
| 800 |
+
else:
|
| 801 |
+
plan["generation"] = None
|
| 802 |
+
plan["execution_state"] = "NOT_REQUESTED"
|
| 803 |
# If the routed primary expert is CODE, this turn is on the code-emission
|
| 804 |
# path: gate the intended diff through R1's restraint ladder and attach the
|
| 805 |
# chosen rung + signed restraint receipt (honest PENDING if R1 not live yet).
|
|
|
|
| 823 |
"""A governed code-emission turn. `intent` is the natural-language description
|
| 824 |
of the diff SZL-Nemo is about to write (defaults to the query). We route it
|
| 825 |
through restraint BEFORE emitting, surface the rung + ceilings + lines-saved,
|
| 826 |
+
and sign the combined decision. Code generation is not performed by this path;
|
| 827 |
+
this returns
|
| 828 |
the GOVERNED, restraint-gated code PLAN + a signed receipt, honestly labelled."""
|
| 829 |
task = (intent or query or "").strip()
|
| 830 |
route = govern_route(query, top_k=2, sign_fn=None)
|
|
|
|
| 843 |
"overall_lambda_advisory": route["overall_lambda_advisory"],
|
| 844 |
"skeleton_note": (
|
| 845 |
"GOVERNED CODE PLAN — the intended diff is routed through a11oy "
|
| 846 |
+
"Restraint (R1) BEFORE any code is emitted. This endpoint creates a "
|
| 847 |
+
"governed plan only; no code is fabricated here."),
|
|
|
|
| 848 |
"ponytail": _PONYTAIL,
|
| 849 |
"doctrine": DOCTRINE,
|
| 850 |
"ts_utc": datetime.now(timezone.utc).isoformat(),
|
|
|
|
| 861 |
# sovereign:true ONLY from the live gpu_reachable probe (Dev C). cloud = false.
|
| 862 |
# ---------------------------------------------------------------------------
|
| 863 |
def tiers_view():
|
| 864 |
+
runtime = nemo_runtime_status()
|
| 865 |
+
ready = runtime.get("state") == "READY"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 866 |
local_tier = {
|
| 867 |
"tier_id": "sovereign-local",
|
| 868 |
+
"title": "Sovereign-Local Nemotron Recipe",
|
| 869 |
"where": "gpu",
|
| 870 |
+
"sovereign": ready,
|
| 871 |
+
"gpu_reachable": ready,
|
| 872 |
+
"node_serving_now": runtime.get("served_model") if ready else None,
|
| 873 |
"base_model": NEMO_BASE["default_base"] + " (open base, " +
|
| 874 |
NEMO_BASE["default_base_license"] + ")",
|
| 875 |
+
"plan": "Exact Ollama recipe on SZL-controlled local hardware.",
|
| 876 |
+
"base_url": runtime.get("endpoint"),
|
| 877 |
+
"probe_note": runtime,
|
| 878 |
+
"label": "MEASURED" if ready else "UNAVAILABLE",
|
| 879 |
+
"honesty": runtime.get("honesty"),
|
|
|
|
|
|
|
| 880 |
}
|
| 881 |
cloud_tier = {
|
| 882 |
"tier_id": "cloud-NIM-frontier",
|
|
|
|
| 899 |
"schema": "szl.nemo.tiers/v1",
|
| 900 |
"model": NEMO_NAME,
|
| 901 |
"tiers": [local_tier, cloud_tier],
|
| 902 |
+
"future": ("Larger local or cloud tiers remain separate candidates and must "
|
| 903 |
+
"pass their own identity, license, quality, and runtime receipts."),
|
| 904 |
"doctrine": ("sovereign:true only via live probe; measured > datasheet; "
|
| 905 |
"0 CDN; signed receipts; never commit a key."),
|
| 906 |
"ts_utc": datetime.now(timezone.utc).isoformat(),
|
|
|
|
| 1070 |
return {
|
| 1071 |
"schema": "szl.nemo.model_card/v1",
|
| 1072 |
"name": NEMO_NAME, "version": NEMO_VERSION,
|
| 1073 |
+
"one_liner": ("SZL-Nemo — a governed local recipe and orchestration runtime "
|
| 1074 |
+
"built on NVIDIA Nemotron 3 Nano 4B."),
|
| 1075 |
"base": NEMO_BASE,
|
| 1076 |
"hub_artifact": NEMO_ARTIFACT,
|
| 1077 |
"what_is_ours": [
|
| 1078 |
"Governed-MoE DOMAIN-EXPERT router (Λ-governed, signed every selection) — the differentiator.",
|
| 1079 |
+
"Fail-closed loopback serving with exact upstream and derived-tag identity binding.",
|
| 1080 |
"Reflexion + Voyager + τ-bench self-improvement loop that SIGNS the measured delta.",
|
| 1081 |
+
"Tiered local/cloud gateway with honest where/sovereign labels.",
|
| 1082 |
"Tamper-evident DSSE ECDSA-P256 signed receipts on every governed step.",
|
| 1083 |
],
|
| 1084 |
"what_is_NOT_ours": [
|
| 1085 |
+
"The base weights (NVIDIA, cited above, under the upstream model license).",
|
| 1086 |
"We did NOT train a foundation model from scratch.",
|
| 1087 |
+
"The current SZL-Nemo recipe is NOT an SZL fine-tune.",
|
| 1088 |
"There is NO 550B SZL model and NO local Nemotron-Ultra (cloud tier only).",
|
| 1089 |
],
|
| 1090 |
"experts": [{"id": e["id"], "title": e["title"], "desc": e["desc"]} for e in NEMO_EXPERTS],
|
|
|
|
| 1093 |
"tiers": tiers_view(),
|
| 1094 |
"doctrine": DOCTRINE,
|
| 1095 |
"never_claim": NEMO_BASE["never_claim"],
|
| 1096 |
+
"runtime": nemo_runtime_status(),
|
| 1097 |
"sources": {
|
| 1098 |
+
"base_nemotron": NEMO_BASE["default_base_url"],
|
| 1099 |
+
"base_license": NEMO_BASE["license_url"],
|
| 1100 |
+
"hub_recipe": NEMO_ARTIFACT["url"],
|
| 1101 |
"speculative_decoding": "https://arxiv.org/abs/2211.17192",
|
| 1102 |
"reflexion": "https://arxiv.org/abs/2303.11366",
|
| 1103 |
"voyager": "https://arxiv.org/abs/2305.16291",
|
|
|
|
| 1157 |
if not q:
|
| 1158 |
return JSONResponse({"error": "missing 'query'"}, status_code=400)
|
| 1159 |
top_k = int(d.get("top_k", 2))
|
| 1160 |
+
execute_value = str(d.get("execute", "true")).strip().lower()
|
| 1161 |
+
execute = execute_value not in {"0", "false", "no", "off"}
|
| 1162 |
+
return JSONResponse(infer(q, top_k=top_k, sign_fn=sign_fn,
|
| 1163 |
+
execute=execute))
|
| 1164 |
|
| 1165 |
async def _code_ep(request):
|
| 1166 |
if request.method == "POST":
|
|
|
|
| 1199 |
async def _diag_ep(request):
|
| 1200 |
return JSONResponse({
|
| 1201 |
"status": "ok", "model": NEMO_NAME, "version": NEMO_VERSION,
|
| 1202 |
+
"runtime": nemo_runtime_status(),
|
| 1203 |
"signer_present": sign_fn is not None,
|
| 1204 |
"signer_label": signer_label,
|
| 1205 |
"reuse": {
|
|
@@ -119,14 +119,14 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 119 |
n_before = len(app.router.routes)
|
| 120 |
|
| 121 |
@app.get("/operator-organ")
|
| 122 |
-
async def _operator_page()
|
| 123 |
f = _PAGES / "operator_organ.html"
|
| 124 |
if f.is_file():
|
| 125 |
return FileResponse(str(f), media_type="text/html; charset=utf-8")
|
| 126 |
return JSONResponse({"error": "operator organ page missing"}, status_code=404)
|
| 127 |
|
| 128 |
@app.get("/operator-organ/app.js")
|
| 129 |
-
async def _operator_js()
|
| 130 |
f = _STATIC / "a11oy_operator_organ.js"
|
| 131 |
if f.is_file():
|
| 132 |
return FileResponse(
|
|
@@ -135,7 +135,7 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 135 |
return JSONResponse({"error": "operator organ js missing"}, status_code=404)
|
| 136 |
|
| 137 |
@app.get("/operator-organ/topology.json")
|
| 138 |
-
async def _operator_topology()
|
| 139 |
try:
|
| 140 |
topo = _build_topology(app)
|
| 141 |
_CACHE["topo"] = topo
|
|
@@ -162,4 +162,4 @@ if __name__ == "__main__":
|
|
| 162 |
class _Stub:
|
| 163 |
class router: # noqa
|
| 164 |
routes = []
|
| 165 |
-
print(json.dumps(_build_topology(_Stub), indent=2))
|
|
|
|
| 119 |
n_before = len(app.router.routes)
|
| 120 |
|
| 121 |
@app.get("/operator-organ")
|
| 122 |
+
async def _operator_page(): # noqa: ANN202
|
| 123 |
f = _PAGES / "operator_organ.html"
|
| 124 |
if f.is_file():
|
| 125 |
return FileResponse(str(f), media_type="text/html; charset=utf-8")
|
| 126 |
return JSONResponse({"error": "operator organ page missing"}, status_code=404)
|
| 127 |
|
| 128 |
@app.get("/operator-organ/app.js")
|
| 129 |
+
async def _operator_js(): # noqa: ANN202
|
| 130 |
f = _STATIC / "a11oy_operator_organ.js"
|
| 131 |
if f.is_file():
|
| 132 |
return FileResponse(
|
|
|
|
| 135 |
return JSONResponse({"error": "operator organ js missing"}, status_code=404)
|
| 136 |
|
| 137 |
@app.get("/operator-organ/topology.json")
|
| 138 |
+
async def _operator_topology(): # noqa: ANN202
|
| 139 |
try:
|
| 140 |
topo = _build_topology(app)
|
| 141 |
_CACHE["topo"] = topo
|
|
|
|
| 162 |
class _Stub:
|
| 163 |
class router: # noqa
|
| 164 |
routes = []
|
| 165 |
+
print(json.dumps(_build_topology(_Stub), indent=2))
|
|
@@ -36,6 +36,12 @@ Build strategy (Series-A grade, honest):
|
|
| 36 |
cannot finish synchronously in-image it runs on a receipted background tick
|
| 37 |
(``refresh_tick`` / ``start_background_build``); status reports
|
| 38 |
``seed|building|full`` truthfully — never a fake "full".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
Graph model (our own original code; GraphRAG-shaped):
|
| 41 |
nodes = {repo, file, symbol, hf_space, recipe}
|
|
@@ -80,6 +86,8 @@ import re
|
|
| 80 |
import sqlite3
|
| 81 |
import threading
|
| 82 |
import time
|
|
|
|
|
|
|
| 83 |
from typing import Any, Callable
|
| 84 |
|
| 85 |
# Λ aggregator + receipts are reused from the shared brain / orchestrator.
|
|
@@ -225,6 +233,14 @@ def corpus_manifest() -> dict[str, Any]:
|
|
| 225 |
|
| 226 |
|
| 227 |
_lock = threading.RLock()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
|
| 229 |
|
| 230 |
# --------------------------------------------------------------------------- #
|
|
@@ -279,6 +295,7 @@ class OrgGraph:
|
|
| 279 |
|
| 280 |
# In-process graph cache (rebuilt by build_index).
|
| 281 |
_GRAPH = OrgGraph()
|
|
|
|
| 282 |
_BUILD_META: dict[str, Any] = {"built": False, "ts": None, "repos": 0, "chunks": 0,
|
| 283 |
"honest_note": "index not built yet — call build_index"}
|
| 284 |
|
|
@@ -287,10 +304,12 @@ _BUILD_META: dict[str, Any] = {"built": False, "ts": None, "repos": 0, "chunks":
|
|
| 287 |
# SQLite FTS5 + vector store
|
| 288 |
# --------------------------------------------------------------------------- #
|
| 289 |
def _db() -> sqlite3.Connection:
|
| 290 |
-
from pathlib import Path
|
| 291 |
Path(RAG_DB_PATH).parent.mkdir(parents=True, exist_ok=True)
|
| 292 |
conn = sqlite3.connect(RAG_DB_PATH, timeout=15)
|
| 293 |
conn.row_factory = sqlite3.Row
|
|
|
|
|
|
|
|
|
|
| 294 |
return conn
|
| 295 |
|
| 296 |
|
|
@@ -322,10 +341,380 @@ def _init_schema(conn: sqlite3.Connection) -> bool:
|
|
| 322 |
"CREATE TABLE IF NOT EXISTS org_vectors("
|
| 323 |
"chunk_id TEXT PRIMARY KEY, dim INTEGER, vec TEXT)"
|
| 324 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 325 |
conn.commit()
|
| 326 |
return has_fts5
|
| 327 |
|
| 328 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
# --------------------------------------------------------------------------- #
|
| 330 |
# GitHub enumeration (the offline build path). Receipted by the caller.
|
| 331 |
# --------------------------------------------------------------------------- #
|
|
@@ -404,8 +793,7 @@ def build_index(repos: list[str] | None = None, max_files_per_repo: int = 120,
|
|
| 404 |
graph = OrgGraph()
|
| 405 |
conn = _db()
|
| 406 |
has_fts5 = _init_schema(conn)
|
| 407 |
-
|
| 408 |
-
conn.execute("DELETE FROM org_vectors")
|
| 409 |
|
| 410 |
if repos is None:
|
| 411 |
try:
|
|
@@ -464,35 +852,40 @@ def build_index(repos: list[str] | None = None, max_files_per_repo: int = 120,
|
|
| 464 |
cid = hashlib.sha256(f"{fid}:{j}".encode()).hexdigest()[:24]
|
| 465 |
csha = hashlib.sha256(seg.encode()).hexdigest()
|
| 466 |
conn.execute(
|
| 467 |
-
"INSERT INTO
|
| 468 |
-
" VALUES(?,?,?,?,?,?,?,?,?,?)",
|
| 469 |
-
(cid, fid, repo, path, "file", _cat,
|
|
|
|
| 470 |
if embed_fn is not None:
|
| 471 |
try:
|
| 472 |
v = embed_fn(seg)
|
| 473 |
conn.execute(
|
| 474 |
-
"INSERT OR REPLACE INTO
|
| 475 |
-
|
|
|
|
|
|
|
| 476 |
except Exception:
|
| 477 |
pass
|
| 478 |
chunk_count += 1
|
| 479 |
conn.commit()
|
| 480 |
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
"
|
| 485 |
"repos": len(repos), "chunks": chunk_count,
|
| 486 |
"fts5": has_fts5, "dense": embed_fn is not None,
|
| 487 |
"node_count": len(graph.nodes), "edge_count": len(graph.edges),
|
| 488 |
"build_ms": round((time.time() - t0) * 1000, 1),
|
| 489 |
"corpus_categories": sorted({_category_for(r) for r in repos}),
|
|
|
|
| 490 |
"honest_note": ("dense vectors present" if embed_fn is not None
|
| 491 |
else "FTS5/lexical only — embedding model unavailable in this runtime (honest)"),
|
| 492 |
}
|
|
|
|
| 493 |
conn.close()
|
| 494 |
-
rec = emit_receipt("org_rag.index.built",
|
| 495 |
-
out = {"ok":
|
| 496 |
if rec:
|
| 497 |
out["khipu_hash"] = rec.get("hash")
|
| 498 |
return out
|
|
@@ -537,7 +930,12 @@ def dense_vector_count() -> int:
|
|
| 537 |
try:
|
| 538 |
conn = _db()
|
| 539 |
try:
|
| 540 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 541 |
return int(row["n"]) if row else 0
|
| 542 |
finally:
|
| 543 |
conn.close()
|
|
@@ -550,7 +948,12 @@ def chunk_count() -> int:
|
|
| 550 |
try:
|
| 551 |
conn = _db()
|
| 552 |
try:
|
| 553 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 554 |
return int(row["n"]) if row else 0
|
| 555 |
finally:
|
| 556 |
conn.close()
|
|
@@ -569,10 +972,19 @@ def next_unembedded_chunks(limit: int = 4) -> list[dict[str, Any]]:
|
|
| 569 |
try:
|
| 570 |
conn = _db()
|
| 571 |
try:
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 576 |
for r in rows:
|
| 577 |
out.append({"chunk_id": r["chunk_id"], "repo": r["repo"],
|
| 578 |
"path": r["path"], "corpus": r["corpus"],
|
|
@@ -590,13 +1002,19 @@ def embed_and_store_chunk(chunk_id: str, vec: list[float]) -> dict[str, Any]:
|
|
| 590 |
org_chunks — we never create a chunk row here, so an indexed chunk can never be
|
| 591 |
fabricated. Returns {ok, chunk_id, dim} or an honest error. Uses the SAME
|
| 592 |
storage format as _ingest_text (json list, 6-dp rounding)."""
|
|
|
|
| 593 |
if not chunk_id or not isinstance(vec, (list, tuple)) or len(vec) == 0:
|
| 594 |
return {"ok": False, "honest_error": "empty chunk_id or vector — nothing stored"}
|
| 595 |
try:
|
| 596 |
conn = _db()
|
| 597 |
try:
|
| 598 |
-
|
| 599 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 600 |
if not exists:
|
| 601 |
# Honest refusal: cannot add a vector for a chunk that was never
|
| 602 |
# really ingested (would imply a fabricated indexed chunk).
|
|
@@ -604,10 +1022,44 @@ def embed_and_store_chunk(chunk_id: str, vec: list[float]) -> dict[str, Any]:
|
|
| 604 |
"honest_error": "chunk_id not present in org_chunks — refusing "
|
| 605 |
"to store a vector for a non-existent chunk "
|
| 606 |
"(Zero-Bandaid Law: never fabricate an index)"}
|
| 607 |
-
|
| 608 |
-
|
| 609 |
-
|
| 610 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
finally:
|
| 612 |
conn.close()
|
| 613 |
except Exception as exc:
|
|
@@ -796,7 +1248,8 @@ def _local_provenance(rel_from_corpus: str) -> dict[str, str]:
|
|
| 796 |
|
| 797 |
def _ingest_local_category(graph: OrgGraph, conn: sqlite3.Connection, *, category: str,
|
| 798 |
local_dirs: list[str],
|
| 799 |
-
embed_fn: Callable[[str], list[float]] | None
|
|
|
|
| 800 |
) -> tuple[int, int]:
|
| 801 |
"""Ingest the REAL in-image mirror files for one category. Returns
|
| 802 |
(files, chunks). Each chunk is labeled with an honest 'bundled:<repo>@<sha>'
|
|
@@ -833,7 +1286,7 @@ def _ingest_local_category(graph: OrgGraph, conn: sqlite3.Connection, *, categor
|
|
| 833 |
prov = _local_provenance(f"corpus/{rel}/{name}")
|
| 834 |
wrote = _ingest_text(graph, conn, repo=prov["repo"], path=prov["path"],
|
| 835 |
raw=raw, source=prov["source"], category=category,
|
| 836 |
-
embed_fn=embed_fn)
|
| 837 |
files_n += 1
|
| 838 |
chunks_n += wrote
|
| 839 |
return (files_n, chunks_n)
|
|
@@ -841,7 +1294,8 @@ def _ingest_local_category(graph: OrgGraph, conn: sqlite3.Connection, *, categor
|
|
| 841 |
|
| 842 |
def _ingest_text(graph: OrgGraph, conn: sqlite3.Connection, *, repo: str, path: str,
|
| 843 |
raw: str, source: str, category: str,
|
| 844 |
-
embed_fn: Callable[[str], list[float]] | None
|
|
|
|
| 845 |
"""Shared ingest: graph nodes/edges + symbols + imports + FTS5/vector chunks.
|
| 846 |
Returns the number of chunks written. Used by seed AND full builds so the two
|
| 847 |
paths are byte-for-byte consistent in how they ground + cite."""
|
|
@@ -861,15 +1315,16 @@ def _ingest_text(graph: OrgGraph, conn: sqlite3.Connection, *, repo: str, path:
|
|
| 861 |
cid = hashlib.sha256(f"{source}:{fid}:{j}".encode()).hexdigest()[:24]
|
| 862 |
csha = hashlib.sha256(seg.encode()).hexdigest()
|
| 863 |
conn.execute(
|
| 864 |
-
"INSERT INTO
|
| 865 |
-
" VALUES(?,?,?,?,?,?,?,?,?,?)",
|
| 866 |
-
(cid, fid, repo, path, "file", category, source, path, seg, csha))
|
| 867 |
if embed_fn is not None:
|
| 868 |
try:
|
| 869 |
v = embed_fn(seg)
|
| 870 |
conn.execute(
|
| 871 |
-
"INSERT OR REPLACE INTO
|
| 872 |
-
(
|
|
|
|
| 873 |
except Exception:
|
| 874 |
pass
|
| 875 |
n += 1
|
|
@@ -888,8 +1343,7 @@ def build_seed_index(emit_receipt: Callable[[str, dict], dict] | None = None) ->
|
|
| 888 |
graph = OrgGraph()
|
| 889 |
conn = _db()
|
| 890 |
has_fts5 = _init_schema(conn)
|
| 891 |
-
|
| 892 |
-
conn.execute("DELETE FROM org_vectors")
|
| 893 |
embed_fn = _maybe_embedder()
|
| 894 |
per_cat: dict[str, dict[str, int]] = {}
|
| 895 |
chunk_count = 0
|
|
@@ -921,7 +1375,8 @@ def build_seed_index(emit_receipt: Callable[[str, dict], dict] | None = None) ->
|
|
| 921 |
continue
|
| 922 |
repo_for = src.split("/")[-1]
|
| 923 |
wrote = _ingest_text(graph, conn, repo=repo_for, path=path, raw=raw,
|
| 924 |
-
source=src, category=cat, embed_fn=embed_fn
|
|
|
|
| 925 |
c_files += 1
|
| 926 |
c_chunks += wrote
|
| 927 |
chunk_count += wrote
|
|
@@ -932,7 +1387,8 @@ def build_seed_index(emit_receipt: Callable[[str, dict], dict] | None = None) ->
|
|
| 932 |
local_dirs = spec.get("local_paths", [])
|
| 933 |
if c_files == 0 and local_dirs:
|
| 934 |
lf, lc = _ingest_local_category(graph, conn, category=cat,
|
| 935 |
-
local_dirs=local_dirs, embed_fn=embed_fn
|
|
|
|
| 936 |
c_files += lf
|
| 937 |
c_chunks += lc
|
| 938 |
chunk_count += lc
|
|
@@ -940,15 +1396,16 @@ def build_seed_index(emit_receipt: Callable[[str, dict], dict] | None = None) ->
|
|
| 940 |
per_cat[cat] = {"files": c_files, "chunks": c_chunks}
|
| 941 |
conn.commit()
|
| 942 |
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
"
|
| 947 |
"repos": len({s for s in per_cat}), "chunks": chunk_count, "files": files_ok,
|
| 948 |
"fts5": has_fts5, "dense": embed_fn is not None,
|
| 949 |
"node_count": len(graph.nodes), "edge_count": len(graph.edges),
|
| 950 |
"build_ms": round((time.time() - t0) * 1000, 1),
|
| 951 |
"per_category": per_cat,
|
|
|
|
| 952 |
"corpus_categories": [c for c, v in per_cat.items() if v["chunks"] > 0],
|
| 953 |
"gh_credential": bool(gh), "hf_credential": bool(hf),
|
| 954 |
"honest_note": (
|
|
@@ -961,10 +1418,11 @@ def build_seed_index(emit_receipt: Callable[[str, dict], dict] | None = None) ->
|
|
| 961 |
"szl-holdings repos read UNAUTHENTICATED (rate-limited but real); "
|
| 962 |
"HF Spaces also ingested (honest, not fabricated).")),
|
| 963 |
}
|
|
|
|
| 964 |
conn.close()
|
| 965 |
-
rec = emit_receipt("org_rag.index.seed",
|
| 966 |
-
out = {"ok":
|
| 967 |
-
if not
|
| 968 |
out["honest_error"] = ("seed index empty — no corpus file could be fetched "
|
| 969 |
"(no GitHub/HF credential reachable). NOT claiming a "
|
| 970 |
"built index (Zero-Bandaid Law).")
|
|
@@ -987,8 +1445,7 @@ def build_full_corpus(emit_receipt: Callable[[str, dict], dict] | None = None,
|
|
| 987 |
graph = OrgGraph()
|
| 988 |
conn = _db()
|
| 989 |
has_fts5 = _init_schema(conn)
|
| 990 |
-
|
| 991 |
-
conn.execute("DELETE FROM org_vectors")
|
| 992 |
embed_fn = _maybe_embedder()
|
| 993 |
per_cat: dict[str, dict[str, int]] = {}
|
| 994 |
chunk_count = 0
|
|
@@ -1029,7 +1486,8 @@ def build_full_corpus(emit_receipt: Callable[[str, dict], dict] | None = None,
|
|
| 1029 |
continue
|
| 1030 |
wrote = _ingest_text(graph, conn, repo=repo, path=f["path"],
|
| 1031 |
raw=raw, source=f"gh:{ORG}/{repo}",
|
| 1032 |
-
category=cat, embed_fn=embed_fn
|
|
|
|
| 1033 |
c_files += 1
|
| 1034 |
c_chunks += wrote
|
| 1035 |
chunk_count += wrote
|
|
@@ -1043,7 +1501,8 @@ def build_full_corpus(emit_receipt: Callable[[str, dict], dict] | None = None,
|
|
| 1043 |
continue
|
| 1044 |
wrote = _ingest_text(graph, conn, repo=sp, path=path, raw=raw,
|
| 1045 |
source=f"hf:{HF_ORG}/{sp}", category=cat,
|
| 1046 |
-
embed_fn=embed_fn
|
|
|
|
| 1047 |
c_files += 1
|
| 1048 |
c_chunks += wrote
|
| 1049 |
chunk_count += wrote
|
|
@@ -1056,7 +1515,8 @@ def build_full_corpus(emit_receipt: Callable[[str, dict], dict] | None = None,
|
|
| 1056 |
local_dirs = spec.get("local_paths", [])
|
| 1057 |
if c_files == 0 and local_dirs:
|
| 1058 |
lf, lc = _ingest_local_category(graph, conn, category=cat,
|
| 1059 |
-
local_dirs=local_dirs, embed_fn=embed_fn
|
|
|
|
| 1060 |
c_files += lf
|
| 1061 |
c_chunks += lc
|
| 1062 |
chunk_count += lc
|
|
@@ -1067,15 +1527,16 @@ def build_full_corpus(emit_receipt: Callable[[str, dict], dict] | None = None,
|
|
| 1067 |
"category": cat, "files": c_files, "chunks": c_chunks})
|
| 1068 |
|
| 1069 |
built_cats = [c for c, v in per_cat.items() if v["chunks"] > 0]
|
| 1070 |
-
|
| 1071 |
-
|
| 1072 |
-
|
| 1073 |
-
"
|
| 1074 |
"repos": len(seen_repo), "chunks": chunk_count,
|
| 1075 |
"fts5": has_fts5, "dense": embed_fn is not None,
|
| 1076 |
"node_count": len(graph.nodes), "edge_count": len(graph.edges),
|
| 1077 |
"build_ms": round((time.time() - t0) * 1000, 1),
|
| 1078 |
"per_category": per_cat, "corpus_categories": built_cats,
|
|
|
|
| 1079 |
"gh_credential": bool(gh),
|
| 1080 |
"corpus_mirror": bool(_corpus_root()),
|
| 1081 |
"honest_note": (
|
|
@@ -1091,9 +1552,10 @@ def build_full_corpus(emit_receipt: Callable[[str, dict], dict] | None = None,
|
|
| 1091 |
"source='bundled:<repo>@<commit_sha>:<path>' — real files, honest "
|
| 1092 |
"provenance, NOT fabricated." if _corpus_root() else "")),
|
| 1093 |
}
|
|
|
|
| 1094 |
conn.close()
|
| 1095 |
-
rec = emit_receipt("org_rag.index.full",
|
| 1096 |
-
out = {"ok":
|
| 1097 |
if rec:
|
| 1098 |
out["khipu_hash"] = rec.get("hash")
|
| 1099 |
return out
|
|
@@ -1187,39 +1649,101 @@ def query(q: str, k: int = 6, repo: str | None = None,
|
|
| 1187 |
``file{path,sha256}`` evidence, plus an ``i_dont_know`` flag when support is
|
| 1188 |
too low. ``hyde_text`` (optional) is a hypothetical answer used for dense
|
| 1189 |
recall (HyDE) instead of the bare query."""
|
|
|
|
| 1190 |
if not _BUILD_META.get("built"):
|
| 1191 |
return {"ok": False, "i_dont_know": True,
|
| 1192 |
"honest_error": "org index not built — call /api/a11oy/code/rag/index first",
|
| 1193 |
"query": q, "chunks": []}
|
| 1194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1195 |
embed_fn = _maybe_embedder()
|
| 1196 |
recall_text = hyde_text or q
|
| 1197 |
# Stage 1: lexical recall (FTS5 or LIKE fallback).
|
| 1198 |
-
rows: list[
|
| 1199 |
try:
|
| 1200 |
-
|
| 1201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1202 |
if repo:
|
| 1203 |
sql += " AND repo = ?"
|
| 1204 |
args.append(repo)
|
| 1205 |
sql += " LIMIT ?"
|
| 1206 |
args.append(max(k * 4, 24))
|
| 1207 |
-
rows =
|
|
|
|
| 1208 |
except Exception:
|
| 1209 |
# LIKE fallback (non-FTS5 runtime) — labeled weaker.
|
| 1210 |
like = f"%{re.sub(r'[^A-Za-z0-9_ ]', ' ', q)[:60]}%"
|
| 1211 |
-
|
| 1212 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1213 |
if repo:
|
| 1214 |
sql += " AND repo = ?"
|
| 1215 |
args.append(repo)
|
| 1216 |
sql += " LIMIT ?"
|
| 1217 |
args.append(max(k * 4, 24))
|
| 1218 |
try:
|
| 1219 |
-
rows =
|
|
|
|
| 1220 |
except Exception:
|
| 1221 |
rows = []
|
| 1222 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1223 |
# dense vector for query (HyDE-aware)
|
| 1224 |
qvec = None
|
| 1225 |
if embed_fn is not None:
|
|
@@ -1237,14 +1761,18 @@ def query(q: str, k: int = 6, repo: str | None = None,
|
|
| 1237 |
lexical = (len(qtokens & btokens) / (len(qtokens) + 1e-9)) if qtokens else 0.0
|
| 1238 |
lexical = min(1.0, lexical)
|
| 1239 |
semantic = lexical
|
| 1240 |
-
if qvec is not None:
|
| 1241 |
-
row = conn.execute(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1242 |
if row:
|
| 1243 |
try:
|
| 1244 |
semantic = max(0.0, _cosine(qvec, json.loads(row["vec"])))
|
| 1245 |
except Exception:
|
| 1246 |
pass
|
| 1247 |
-
centrality =
|
| 1248 |
# conformal anti-overconfidence floor 1/(n+1) over the recall set.
|
| 1249 |
conformal = 1.0 - 1.0 / (len(rows) + 1)
|
| 1250 |
# Λ over the three relevance axes (geometric mean — never 1.0 unless all 1.0).
|
|
@@ -1252,23 +1780,53 @@ def query(q: str, k: int = 6, repo: str | None = None,
|
|
| 1252 |
_cols = r.keys()
|
| 1253 |
corpus = (r["corpus"] if "corpus" in _cols else None) or _category_for(r["repo"])
|
| 1254 |
source = (r["source"] if "source" in _cols else None) or f"gh:{ORG}/{r['repo']}"
|
| 1255 |
-
|
| 1256 |
"chunk_id": r["chunk_id"], "node_id": r["node_id"], "repo": r["repo"],
|
| 1257 |
"path": r["path"], "title": r["title"], "text": body[:1200],
|
| 1258 |
"sha256": r["sha256"], "corpus": corpus, "source": source,
|
| 1259 |
"scores": {"semantic": round(semantic, 4), "lexical": round(lexical, 4),
|
| 1260 |
"centrality": round(centrality, 4), "conformal": round(conformal, 4)},
|
| 1261 |
"lambda": round(lam, 4),
|
|
|
|
| 1262 |
# M2M evidence of kind file{path,sha256} — carries corpus+source so the
|
| 1263 |
# agent CITES exactly where each grounded claim came from (founder mandate).
|
| 1264 |
"evidence": {"kind": "file", "path": f"{r['repo']}/{r['path']}",
|
| 1265 |
"sha256": r["sha256"], "corpus": corpus, "source": source,
|
| 1266 |
"citation": f"{source}/{r['path']}"},
|
| 1267 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1268 |
conn.close()
|
| 1269 |
scored.sort(key=lambda x: x["lambda"], reverse=True)
|
| 1270 |
grounded = [s for s in scored if s["lambda"] >= _LAMBDA_FLOOR][:k]
|
| 1271 |
i_dont_know = len(grounded) == 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1272 |
out = {
|
| 1273 |
"ok": True,
|
| 1274 |
"query": q,
|
|
@@ -1277,21 +1835,33 @@ def query(q: str, k: int = 6, repo: str | None = None,
|
|
| 1277 |
"lambda_floor": _LAMBDA_FLOOR,
|
| 1278 |
"recall_count": len(scored),
|
| 1279 |
"grounded_count": len(grounded),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1280 |
"i_dont_know": i_dont_know,
|
| 1281 |
"chunks": grounded,
|
|
|
|
|
|
|
| 1282 |
"honest_note": ("no chunk cleared the Λ relevance floor — returning i_dont_know "
|
| 1283 |
"rather than fabricating support (Self-RAG)") if i_dont_know else None,
|
| 1284 |
}
|
| 1285 |
if emit_receipt:
|
| 1286 |
rec = emit_receipt("org_rag.query", {
|
| 1287 |
"query": q[:120], "grounded": len(grounded), "i_dont_know": i_dont_know,
|
| 1288 |
-
"dense": qvec is not None
|
|
|
|
| 1289 |
out["khipu_hash"] = rec.get("hash")
|
| 1290 |
return out
|
| 1291 |
|
| 1292 |
|
| 1293 |
def repo_map(repo: str) -> dict[str, Any]:
|
| 1294 |
"""Aider-style repo map: files → symbols, ranked by Λ-weighted graph centrality."""
|
|
|
|
| 1295 |
if not _BUILD_META.get("built"):
|
| 1296 |
return {"ok": False, "honest_error": "org index not built — call build_index first",
|
| 1297 |
"repo": repo}
|
|
@@ -1309,6 +1879,7 @@ def repo_map(repo: str) -> dict[str, Any]:
|
|
| 1309 |
|
| 1310 |
def graph_dict() -> dict[str, Any]:
|
| 1311 |
"""Org graph for the 3D UI (nodes/edges). Honest empty state if not built."""
|
|
|
|
| 1312 |
d = _GRAPH.to_dict()
|
| 1313 |
d["built"] = _BUILD_META.get("built", False)
|
| 1314 |
d["meta"] = _BUILD_META
|
|
@@ -1316,8 +1887,18 @@ def graph_dict() -> dict[str, Any]:
|
|
| 1316 |
|
| 1317 |
|
| 1318 |
def status() -> dict[str, Any]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1319 |
return {"ok": True, **_BUILD_META, "db_path": RAG_DB_PATH,
|
| 1320 |
"lambda_floor": _LAMBDA_FLOOR,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1321 |
"corpus": corpus_manifest(),
|
| 1322 |
"build_state": build_state()}
|
| 1323 |
|
|
@@ -1363,9 +1944,16 @@ def build_waqay_backend(bit_width: int = 2,
|
|
| 1363 |
return {"ok": False, "honest_error": f"szl_waqay unavailable: {e}", "label": "WAQAY"}
|
| 1364 |
conn = _db()
|
| 1365 |
try:
|
| 1366 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1367 |
except Exception as e:
|
|
|
|
| 1368 |
return {"ok": False, "honest_error": f"org_vectors unavailable: {e}", "label": "WAQAY"}
|
|
|
|
| 1369 |
if not rows:
|
| 1370 |
return {"ok": False, "honest_error": "no dense vectors in org_vectors "
|
| 1371 |
"(FTS5-only runtime) — WAQAY needs an embedding model present",
|
|
@@ -1390,6 +1978,7 @@ def build_waqay_backend(bit_width: int = 2,
|
|
| 1390 |
_WAQAY_INDEX = idx
|
| 1391 |
comp = idx.compression()
|
| 1392 |
_WAQAY_META = {"built": True, "n": len(ids), "dim": dim, "bit_width": bit_width,
|
|
|
|
| 1393 |
"compression_MEASURED": comp,
|
| 1394 |
"recall_MODELED": szl_waqay.WaqayIndex.modeled_recall_bound(bit_width),
|
| 1395 |
"label": "WAQAY"}
|
|
@@ -1418,7 +2007,9 @@ def waqay_query(q: str, k: int = 6, repo: str | None = None,
|
|
| 1418 |
return {"ok": False, "honest_error": f"szl_waqay unavailable: {e}",
|
| 1419 |
"fallback": query(q, k=k, repo=repo, hyde_text=hyde_text,
|
| 1420 |
emit_receipt=emit_receipt)}
|
| 1421 |
-
|
|
|
|
|
|
|
| 1422 |
b = build_waqay_backend(emit_receipt=emit_receipt)
|
| 1423 |
if not b.get("ok"):
|
| 1424 |
# honest fallback to exact path — opting in never costs recall.
|
|
@@ -1437,12 +2028,18 @@ def waqay_query(q: str, k: int = 6, repo: str | None = None,
|
|
| 1437 |
allow=allow, data_label="LIVE")
|
| 1438 |
# Hydrate returned chunk ids with their text from org_chunks.
|
| 1439 |
conn = _db()
|
|
|
|
|
|
|
| 1440 |
chunks = []
|
| 1441 |
for item in gres.get("results", []):
|
| 1442 |
cid = item["id"]
|
| 1443 |
try:
|
| 1444 |
-
row = conn.execute(
|
| 1445 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1446 |
except Exception:
|
| 1447 |
row = None
|
| 1448 |
if row is not None:
|
|
@@ -1453,6 +2050,7 @@ def waqay_query(q: str, k: int = 6, repo: str | None = None,
|
|
| 1453 |
"evidence": {"file": {"path": row["path"], "sha256": row["sha256"]}}})
|
| 1454 |
else:
|
| 1455 |
chunks.append({"chunk_id": cid, "score_approx": item["score"]})
|
|
|
|
| 1456 |
if emit_receipt:
|
| 1457 |
emit_receipt("org_rag.waqay.query", {"query": q[:120], "k": k,
|
| 1458 |
"returned": [c["chunk_id"] for c in chunks]})
|
|
|
|
| 36 |
cannot finish synchronously in-image it runs on a receipted background tick
|
| 37 |
(``refresh_tick`` / ``start_background_build``); status reports
|
| 38 |
``seed|building|full`` truthfully — never a fake "full".
|
| 39 |
+
* Every build writes a versioned staging generation. A single SQLite
|
| 40 |
+
transaction seals its digest/counts and swaps the active pointer; interrupted
|
| 41 |
+
builds remain invisible. Queries pin one active-generation read snapshot.
|
| 42 |
+
* The versioned M1 Brain decision ledger is searchable as metadata handles
|
| 43 |
+
(source URL + receipt + safety/quarantine) in a separate retrieval-only plane.
|
| 44 |
+
It grants exactly zero gradient/training authority.
|
| 45 |
|
| 46 |
Graph model (our own original code; GraphRAG-shaped):
|
| 47 |
nodes = {repo, file, symbol, hf_space, recipe}
|
|
|
|
| 86 |
import sqlite3
|
| 87 |
import threading
|
| 88 |
import time
|
| 89 |
+
import uuid
|
| 90 |
+
from pathlib import Path
|
| 91 |
from typing import Any, Callable
|
| 92 |
|
| 93 |
# Λ aggregator + receipts are reused from the shared brain / orchestrator.
|
|
|
|
| 233 |
|
| 234 |
|
| 235 |
_lock = threading.RLock()
|
| 236 |
+
# Builders may run for minutes. Queries must not take the builder lock; instead
|
| 237 |
+
# they take this very short lock while pairing the immutable in-memory graph with
|
| 238 |
+
# SQLite's active generation. The SQLite read transaction then pins that
|
| 239 |
+
# generation for the duration of the query.
|
| 240 |
+
_SNAPSHOT_LOCK = threading.RLock()
|
| 241 |
+
|
| 242 |
+
_M1_LEDGER_ENV = "A11OY_M1_BRAIN_LEDGER"
|
| 243 |
+
_M1_LEDGER_DEFAULT = Path(__file__).resolve().parent / "model_release" / "m1" / "brain-ingest-ledger.jsonl"
|
| 244 |
|
| 245 |
|
| 246 |
# --------------------------------------------------------------------------- #
|
|
|
|
| 295 |
|
| 296 |
# In-process graph cache (rebuilt by build_index).
|
| 297 |
_GRAPH = OrgGraph()
|
| 298 |
+
_REHYDRATE_ATTEMPTED = False
|
| 299 |
_BUILD_META: dict[str, Any] = {"built": False, "ts": None, "repos": 0, "chunks": 0,
|
| 300 |
"honest_note": "index not built yet — call build_index"}
|
| 301 |
|
|
|
|
| 304 |
# SQLite FTS5 + vector store
|
| 305 |
# --------------------------------------------------------------------------- #
|
| 306 |
def _db() -> sqlite3.Connection:
|
|
|
|
| 307 |
Path(RAG_DB_PATH).parent.mkdir(parents=True, exist_ok=True)
|
| 308 |
conn = sqlite3.connect(RAG_DB_PATH, timeout=15)
|
| 309 |
conn.row_factory = sqlite3.Row
|
| 310 |
+
conn.execute("PRAGMA busy_timeout=15000")
|
| 311 |
+
conn.execute("PRAGMA journal_mode=WAL")
|
| 312 |
+
conn.execute("PRAGMA synchronous=FULL")
|
| 313 |
return conn
|
| 314 |
|
| 315 |
|
|
|
|
| 341 |
"CREATE TABLE IF NOT EXISTS org_vectors("
|
| 342 |
"chunk_id TEXT PRIMARY KEY, dim INTEGER, vec TEXT)"
|
| 343 |
)
|
| 344 |
+
conn.execute(
|
| 345 |
+
"CREATE TABLE IF NOT EXISTS org_runtime_meta("
|
| 346 |
+
"key TEXT PRIMARY KEY, value TEXT NOT NULL)"
|
| 347 |
+
)
|
| 348 |
+
# Generation tables are additive so old installations can be opened and
|
| 349 |
+
# rebuilt without destructive migration. A generation is immutable once it
|
| 350 |
+
# becomes ACTIVE; only the singleton pointer changes during publication.
|
| 351 |
+
conn.execute(
|
| 352 |
+
"CREATE TABLE IF NOT EXISTS org_generations("
|
| 353 |
+
"generation_id TEXT PRIMARY KEY, status TEXT NOT NULL, mode TEXT NOT NULL, "
|
| 354 |
+
"created_at REAL NOT NULL, activated_at REAL, chunk_count INTEGER NOT NULL DEFAULT 0, "
|
| 355 |
+
"vector_count INTEGER NOT NULL DEFAULT 0, brain_handle_count INTEGER NOT NULL DEFAULT 0, "
|
| 356 |
+
"graph_json TEXT, meta_json TEXT, digest_sha256 TEXT, failure_reason TEXT)"
|
| 357 |
+
)
|
| 358 |
+
conn.execute(
|
| 359 |
+
"CREATE TABLE IF NOT EXISTS org_active_generation("
|
| 360 |
+
"singleton INTEGER PRIMARY KEY CHECK(singleton=1), generation_id TEXT NOT NULL)"
|
| 361 |
+
)
|
| 362 |
+
if has_fts5:
|
| 363 |
+
conn.execute(
|
| 364 |
+
"CREATE VIRTUAL TABLE IF NOT EXISTS org_chunks_gen USING fts5("
|
| 365 |
+
"generation_id UNINDEXED, chunk_id UNINDEXED, node_id UNINDEXED, "
|
| 366 |
+
"repo UNINDEXED, path UNINDEXED, kind UNINDEXED, corpus UNINDEXED, "
|
| 367 |
+
"source UNINDEXED, title, body, sha256 UNINDEXED)"
|
| 368 |
+
)
|
| 369 |
+
conn.execute(
|
| 370 |
+
"CREATE VIRTUAL TABLE IF NOT EXISTS org_brain_handles_gen USING fts5("
|
| 371 |
+
"generation_id UNINDEXED, handle_id UNINDEXED, node_id UNINDEXED, "
|
| 372 |
+
"source UNINDEXED, source_url UNINDEXED, receipt_id UNINDEXED, "
|
| 373 |
+
"safety_decision UNINDEXED, training_decision UNINDEXED, "
|
| 374 |
+
"source_training_eligible UNINDEXED, title, metadata_text)"
|
| 375 |
+
)
|
| 376 |
+
else:
|
| 377 |
+
conn.execute(
|
| 378 |
+
"CREATE TABLE IF NOT EXISTS org_chunks_gen("
|
| 379 |
+
"generation_id TEXT, chunk_id TEXT, node_id TEXT, repo TEXT, path TEXT, "
|
| 380 |
+
"kind TEXT, corpus TEXT, source TEXT, title TEXT, body TEXT, sha256 TEXT)"
|
| 381 |
+
)
|
| 382 |
+
conn.execute(
|
| 383 |
+
"CREATE TABLE IF NOT EXISTS org_brain_handles_gen("
|
| 384 |
+
"generation_id TEXT, handle_id TEXT, node_id TEXT, source TEXT, "
|
| 385 |
+
"source_url TEXT, receipt_id TEXT, safety_decision TEXT, "
|
| 386 |
+
"training_decision TEXT, source_training_eligible TEXT, title TEXT, "
|
| 387 |
+
"metadata_text TEXT)"
|
| 388 |
+
)
|
| 389 |
+
conn.execute(
|
| 390 |
+
"CREATE TABLE IF NOT EXISTS org_vectors_gen("
|
| 391 |
+
"generation_id TEXT NOT NULL, chunk_id TEXT NOT NULL, dim INTEGER, vec TEXT, "
|
| 392 |
+
"PRIMARY KEY(generation_id,chunk_id))"
|
| 393 |
+
)
|
| 394 |
conn.commit()
|
| 395 |
return has_fts5
|
| 396 |
|
| 397 |
|
| 398 |
+
def _active_generation(conn: sqlite3.Connection) -> str | None:
|
| 399 |
+
row = conn.execute(
|
| 400 |
+
"SELECT generation_id FROM org_active_generation WHERE singleton=1"
|
| 401 |
+
).fetchone()
|
| 402 |
+
return str(row["generation_id"]) if row else None
|
| 403 |
+
|
| 404 |
+
|
| 405 |
+
def _begin_generation(conn: sqlite3.Connection, mode: str) -> str:
|
| 406 |
+
generation_id = f"{int(time.time() * 1_000_000)}-{uuid.uuid4().hex[:12]}"
|
| 407 |
+
conn.execute(
|
| 408 |
+
"INSERT INTO org_generations(generation_id,status,mode,created_at) VALUES(?,?,?,?)",
|
| 409 |
+
(generation_id, "BUILDING", mode, time.time()),
|
| 410 |
+
)
|
| 411 |
+
conn.commit()
|
| 412 |
+
return generation_id
|
| 413 |
+
|
| 414 |
+
|
| 415 |
+
def _canonical_json(value: Any) -> str:
|
| 416 |
+
return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
| 417 |
+
|
| 418 |
+
|
| 419 |
+
def _generation_digest(conn: sqlite3.Connection, generation_id: str,
|
| 420 |
+
graph_data: dict[str, Any]) -> tuple[str, dict[str, int]]:
|
| 421 |
+
"""Hash every persisted retrieval row plus the graph, in stable order."""
|
| 422 |
+
h = hashlib.sha256()
|
| 423 |
+
h.update(_canonical_json(graph_data).encode("utf-8"))
|
| 424 |
+
counts: dict[str, int] = {}
|
| 425 |
+
table_specs = (
|
| 426 |
+
("chunks", "org_chunks_gen", ("chunk_id", "node_id", "repo", "path", "kind",
|
| 427 |
+
"corpus", "source", "title", "body", "sha256"),
|
| 428 |
+
"chunk_id"),
|
| 429 |
+
("vectors", "org_vectors_gen", ("chunk_id", "dim", "vec"), "chunk_id"),
|
| 430 |
+
("brain_handles", "org_brain_handles_gen",
|
| 431 |
+
("handle_id", "node_id", "source", "source_url", "receipt_id",
|
| 432 |
+
"safety_decision", "training_decision", "source_training_eligible",
|
| 433 |
+
"title", "metadata_text"), "handle_id"),
|
| 434 |
+
)
|
| 435 |
+
for label, table, columns, order_col in table_specs:
|
| 436 |
+
n = 0
|
| 437 |
+
sql = (f"SELECT {','.join(columns)} FROM {table} WHERE generation_id=? "
|
| 438 |
+
f"ORDER BY {order_col}")
|
| 439 |
+
for row in conn.execute(sql, (generation_id,)):
|
| 440 |
+
h.update(label.encode("ascii"))
|
| 441 |
+
h.update(b"\0")
|
| 442 |
+
h.update(_canonical_json([row[c] for c in columns]).encode("utf-8"))
|
| 443 |
+
h.update(b"\n")
|
| 444 |
+
n += 1
|
| 445 |
+
counts[label] = n
|
| 446 |
+
return h.hexdigest(), counts
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
def _resolve_m1_ledger() -> Path | None:
|
| 450 |
+
raw = os.environ.get(_M1_LEDGER_ENV, "").strip()
|
| 451 |
+
path = Path(raw).expanduser().resolve() if raw else _M1_LEDGER_DEFAULT
|
| 452 |
+
return path if path.is_file() else None
|
| 453 |
+
|
| 454 |
+
|
| 455 |
+
def _verify_m1_ledger(path: Path) -> dict[str, Any]:
|
| 456 |
+
"""Verify the release manifest when using the versioned in-repo M1 ledger."""
|
| 457 |
+
manifest_path = path.with_name("corpus-ingestion-manifest.json")
|
| 458 |
+
expected_sha = None
|
| 459 |
+
expected_rows = None
|
| 460 |
+
if manifest_path.is_file():
|
| 461 |
+
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
| 462 |
+
entry = ((manifest.get("ledgers") or {}).get("brain_nodes") or {})
|
| 463 |
+
expected_sha = entry.get("sha256")
|
| 464 |
+
expected_rows = entry.get("rows")
|
| 465 |
+
h = hashlib.sha256()
|
| 466 |
+
rows = 0
|
| 467 |
+
with path.open("rb") as stream:
|
| 468 |
+
for line in stream:
|
| 469 |
+
h.update(line)
|
| 470 |
+
if line.strip():
|
| 471 |
+
rows += 1
|
| 472 |
+
actual_sha = h.hexdigest()
|
| 473 |
+
if expected_sha and actual_sha != expected_sha:
|
| 474 |
+
raise ValueError("M1 Brain ledger SHA-256 does not match its release manifest")
|
| 475 |
+
if expected_rows is not None and rows != int(expected_rows):
|
| 476 |
+
raise ValueError("M1 Brain ledger row count does not match its release manifest")
|
| 477 |
+
return {"path": str(path), "sha256": actual_sha, "rows": rows,
|
| 478 |
+
"manifest_verified": bool(expected_sha and expected_rows is not None)}
|
| 479 |
+
|
| 480 |
+
|
| 481 |
+
def _brain_handle_text(row: dict[str, Any]) -> tuple[str, str]:
|
| 482 |
+
"""Return bounded metadata text only; never copy an external document body."""
|
| 483 |
+
canonical = str(row.get("canonical_text") or "")
|
| 484 |
+
title_match = re.search(r"(?m)^title:\s*(.+)$", canonical)
|
| 485 |
+
title = (title_match.group(1).strip() if title_match else
|
| 486 |
+
str(row.get("node_id") or "untitled Brain handle"))
|
| 487 |
+
prov = row.get("provenance") if isinstance(row.get("provenance"), dict) else {}
|
| 488 |
+
license_info = row.get("license") if isinstance(row.get("license"), dict) else {}
|
| 489 |
+
freshness = row.get("freshness") if isinstance(row.get("freshness"), dict) else {}
|
| 490 |
+
fields = {
|
| 491 |
+
"title": title,
|
| 492 |
+
"kind": row.get("kind"),
|
| 493 |
+
"source": prov.get("source"),
|
| 494 |
+
"url": prov.get("url"),
|
| 495 |
+
"evidence_label": prov.get("evidence_label"),
|
| 496 |
+
"receipt_id": row.get("receipt_id"),
|
| 497 |
+
"safety_decision": row.get("safety_decision"),
|
| 498 |
+
"training_decision": row.get("training_decision"),
|
| 499 |
+
"license_state": license_info.get("state"),
|
| 500 |
+
"freshness_state": freshness.get("state"),
|
| 501 |
+
}
|
| 502 |
+
return title, "\n".join(f"{k}: {v}" for k, v in fields.items() if v is not None)
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
def _ingest_brain_handles(conn: sqlite3.Connection, generation_id: str,
|
| 506 |
+
ledger_path: Path | None = None) -> dict[str, Any]:
|
| 507 |
+
"""Index M1 rows as retrieval-only metadata handles with zero gradient authority."""
|
| 508 |
+
path = ledger_path or _resolve_m1_ledger()
|
| 509 |
+
if path is None:
|
| 510 |
+
return {"state": "ABSENT", "count": 0, "gradient_authority_rows": 0}
|
| 511 |
+
verified = _verify_m1_ledger(path)
|
| 512 |
+
count = 0
|
| 513 |
+
source_training_eligible_rows = 0
|
| 514 |
+
with path.open(encoding="utf-8") as stream:
|
| 515 |
+
for raw_line in stream:
|
| 516 |
+
if not raw_line.strip():
|
| 517 |
+
continue
|
| 518 |
+
row = json.loads(raw_line)
|
| 519 |
+
node_id = str(row.get("node_id") or "").strip()
|
| 520 |
+
receipt_id = str(row.get("receipt_id") or "").strip()
|
| 521 |
+
if not node_id or not receipt_id:
|
| 522 |
+
raise ValueError("M1 Brain handle is missing node_id or receipt_id")
|
| 523 |
+
prov = row.get("provenance") if isinstance(row.get("provenance"), dict) else {}
|
| 524 |
+
title, metadata_text = _brain_handle_text(row)
|
| 525 |
+
handle_id = hashlib.sha256(
|
| 526 |
+
f"{node_id}\0{receipt_id}".encode("utf-8")
|
| 527 |
+
).hexdigest()
|
| 528 |
+
conn.execute(
|
| 529 |
+
"INSERT INTO org_brain_handles_gen("
|
| 530 |
+
"generation_id,handle_id,node_id,source,source_url,receipt_id,"
|
| 531 |
+
"safety_decision,training_decision,source_training_eligible,title,metadata_text) "
|
| 532 |
+
"VALUES(?,?,?,?,?,?,?,?,?,?,?)",
|
| 533 |
+
(generation_id, handle_id, node_id, str(prov.get("source") or ""),
|
| 534 |
+
str(prov.get("url") or ""), receipt_id,
|
| 535 |
+
str(row.get("safety_decision") or "UNKNOWN"),
|
| 536 |
+
str(row.get("training_decision") or "UNKNOWN"),
|
| 537 |
+
"true" if row.get("training_eligible") is True else "false",
|
| 538 |
+
title, metadata_text),
|
| 539 |
+
)
|
| 540 |
+
if row.get("training_eligible") is True:
|
| 541 |
+
source_training_eligible_rows += 1
|
| 542 |
+
count += 1
|
| 543 |
+
conn.commit()
|
| 544 |
+
if count != int(verified["rows"]):
|
| 545 |
+
raise ValueError("M1 Brain handle ingest count changed during verified read")
|
| 546 |
+
return {"state": "INDEXED_RETRIEVAL_ONLY", "count": count,
|
| 547 |
+
"gradient_authority_rows": 0, "training_authority": "NONE",
|
| 548 |
+
"ledger_sha256": verified["sha256"],
|
| 549 |
+
"manifest_verified": verified["manifest_verified"],
|
| 550 |
+
"source_training_eligible_rows": source_training_eligible_rows}
|
| 551 |
+
|
| 552 |
+
|
| 553 |
+
def _persist_runtime_state(conn: sqlite3.Connection, graph: OrgGraph,
|
| 554 |
+
meta: dict[str, Any],
|
| 555 |
+
generation_id: str | None = None) -> None:
|
| 556 |
+
"""Seal one immutable generation and atomically make it query-active.
|
| 557 |
+
|
| 558 |
+
The optional legacy path is retained for focused callers that populated the
|
| 559 |
+
old tables directly: it copies their rows into a fresh generation before the
|
| 560 |
+
swap. Production builders always pass their staging generation explicitly.
|
| 561 |
+
"""
|
| 562 |
+
global _GRAPH, _BUILD_META
|
| 563 |
+
if generation_id is None:
|
| 564 |
+
generation_id = _begin_generation(conn, str(meta.get("mode") or "legacy-migration"))
|
| 565 |
+
conn.execute(
|
| 566 |
+
"INSERT INTO org_chunks_gen(generation_id,chunk_id,node_id,repo,path,kind,"
|
| 567 |
+
"corpus,source,title,body,sha256) SELECT ?,chunk_id,node_id,repo,path,kind,"
|
| 568 |
+
"corpus,source,title,body,sha256 FROM org_chunks", (generation_id,))
|
| 569 |
+
conn.execute(
|
| 570 |
+
"INSERT OR REPLACE INTO org_vectors_gen(generation_id,chunk_id,dim,vec) "
|
| 571 |
+
"SELECT ?,chunk_id,dim,vec FROM org_vectors", (generation_id,))
|
| 572 |
+
conn.commit()
|
| 573 |
+
|
| 574 |
+
if not meta.get("built"):
|
| 575 |
+
conn.execute(
|
| 576 |
+
"UPDATE org_generations SET status='FAILED',failure_reason=? "
|
| 577 |
+
"WHERE generation_id=? AND status='BUILDING'",
|
| 578 |
+
("empty/unusable build refused before active-generation swap", generation_id),
|
| 579 |
+
)
|
| 580 |
+
conn.commit()
|
| 581 |
+
meta.update({"generation_id": generation_id,
|
| 582 |
+
"integrity_state": "NOT_PUBLISHED_EMPTY_BUILD"})
|
| 583 |
+
return
|
| 584 |
+
|
| 585 |
+
graph_data = graph.to_dict()
|
| 586 |
+
with _SNAPSHOT_LOCK:
|
| 587 |
+
conn.commit()
|
| 588 |
+
conn.execute("BEGIN IMMEDIATE")
|
| 589 |
+
# Seal the exact rows protected by this writer transaction. No writer can
|
| 590 |
+
# change staging data between this digest and the active-pointer swap.
|
| 591 |
+
digest, counts = _generation_digest(conn, generation_id, graph_data)
|
| 592 |
+
meta.update({
|
| 593 |
+
"generation_id": generation_id,
|
| 594 |
+
"generation_digest_sha256": digest,
|
| 595 |
+
"integrity_state": "VERIFIED_AT_PUBLISH",
|
| 596 |
+
"corpus_chunk_count": counts["chunks"],
|
| 597 |
+
"brain_handle_count": counts["brain_handles"],
|
| 598 |
+
"training_authority_rows": 0,
|
| 599 |
+
})
|
| 600 |
+
meta_blob = _canonical_json(meta)
|
| 601 |
+
graph_blob = _canonical_json(graph_data)
|
| 602 |
+
previous = _active_generation(conn)
|
| 603 |
+
if previous and previous != generation_id:
|
| 604 |
+
conn.execute("UPDATE org_generations SET status='SUPERSEDED' WHERE generation_id=?",
|
| 605 |
+
(previous,))
|
| 606 |
+
conn.execute(
|
| 607 |
+
"UPDATE org_generations SET status='ACTIVE',activated_at=?,chunk_count=?,"
|
| 608 |
+
"vector_count=?,brain_handle_count=?,graph_json=?,meta_json=?,digest_sha256=? "
|
| 609 |
+
"WHERE generation_id=? AND status='BUILDING'",
|
| 610 |
+
(time.time(), counts["chunks"], counts["vectors"], counts["brain_handles"],
|
| 611 |
+
graph_blob, meta_blob, digest, generation_id),
|
| 612 |
+
)
|
| 613 |
+
if conn.execute("SELECT changes() AS n").fetchone()["n"] != 1:
|
| 614 |
+
conn.rollback()
|
| 615 |
+
raise RuntimeError("generation publication refused: staging generation not BUILDING")
|
| 616 |
+
conn.execute(
|
| 617 |
+
"INSERT INTO org_active_generation(singleton,generation_id) VALUES(1,?) "
|
| 618 |
+
"ON CONFLICT(singleton) DO UPDATE SET generation_id=excluded.generation_id",
|
| 619 |
+
(generation_id,),
|
| 620 |
+
)
|
| 621 |
+
# Compatibility metadata is informational only. Rehydration trusts the
|
| 622 |
+
# active generation row and re-computes its digest, never these keys.
|
| 623 |
+
for key, value in {"build_meta": meta, "graph": graph_data}.items():
|
| 624 |
+
conn.execute(
|
| 625 |
+
"INSERT OR REPLACE INTO org_runtime_meta(key,value) VALUES(?,?)",
|
| 626 |
+
(key, _canonical_json(value)),
|
| 627 |
+
)
|
| 628 |
+
conn.commit()
|
| 629 |
+
_GRAPH = graph
|
| 630 |
+
_BUILD_META = dict(meta)
|
| 631 |
+
|
| 632 |
+
|
| 633 |
+
def _rehydrate_runtime_state() -> bool:
|
| 634 |
+
"""Restore only a digest-verified ACTIVE generation; mismatch fails closed."""
|
| 635 |
+
global _GRAPH, _BUILD_META, _REHYDRATE_ATTEMPTED
|
| 636 |
+
if _BUILD_META.get("built"):
|
| 637 |
+
return True
|
| 638 |
+
if _REHYDRATE_ATTEMPTED:
|
| 639 |
+
return False
|
| 640 |
+
_REHYDRATE_ATTEMPTED = True
|
| 641 |
+
try:
|
| 642 |
+
if not os.path.exists(RAG_DB_PATH):
|
| 643 |
+
return False
|
| 644 |
+
conn = _db()
|
| 645 |
+
_init_schema(conn)
|
| 646 |
+
conn.execute("BEGIN")
|
| 647 |
+
generation_id = _active_generation(conn)
|
| 648 |
+
if not generation_id:
|
| 649 |
+
conn.close()
|
| 650 |
+
_BUILD_META = {
|
| 651 |
+
"built": False, "ts": None, "repos": 0, "chunks": 0,
|
| 652 |
+
"rehydration_state": "REBUILD_REQUIRED_NO_GENERATION",
|
| 653 |
+
"honest_note": "legacy/unversioned Brain index is not trusted; rebuild required",
|
| 654 |
+
}
|
| 655 |
+
return False
|
| 656 |
+
row = conn.execute(
|
| 657 |
+
"SELECT * FROM org_generations WHERE generation_id=? AND status='ACTIVE'",
|
| 658 |
+
(generation_id,),
|
| 659 |
+
).fetchone()
|
| 660 |
+
if not row or not row["graph_json"] or not row["meta_json"] or not row["digest_sha256"]:
|
| 661 |
+
conn.close()
|
| 662 |
+
raise ValueError("active Brain generation is incomplete")
|
| 663 |
+
graph_data = json.loads(row["graph_json"])
|
| 664 |
+
meta = json.loads(row["meta_json"])
|
| 665 |
+
actual_digest, counts = _generation_digest(conn, generation_id, graph_data)
|
| 666 |
+
conn.close()
|
| 667 |
+
count_match = (
|
| 668 |
+
counts["chunks"] == int(row["chunk_count"])
|
| 669 |
+
and counts["vectors"] == int(row["vector_count"])
|
| 670 |
+
and counts["brain_handles"] == int(row["brain_handle_count"])
|
| 671 |
+
)
|
| 672 |
+
if actual_digest != row["digest_sha256"] or not count_match:
|
| 673 |
+
_GRAPH = OrgGraph()
|
| 674 |
+
_BUILD_META = {
|
| 675 |
+
"built": False, "ts": None, "repos": 0, "chunks": 0,
|
| 676 |
+
"generation_id": generation_id,
|
| 677 |
+
"rehydration_state": "INTEGRITY_MISMATCH_REBUILD_REQUIRED",
|
| 678 |
+
"integrity_state": "FAILED_CLOSED",
|
| 679 |
+
"expected_generation_digest_sha256": row["digest_sha256"],
|
| 680 |
+
"actual_generation_digest_sha256": actual_digest,
|
| 681 |
+
"honest_note": "persisted Brain generation failed integrity validation; rebuild required",
|
| 682 |
+
}
|
| 683 |
+
return False
|
| 684 |
+
if not isinstance(meta, dict) or not meta.get("built"):
|
| 685 |
+
raise ValueError("active Brain generation metadata does not claim a built index")
|
| 686 |
+
graph = OrgGraph()
|
| 687 |
+
if isinstance(graph_data, dict):
|
| 688 |
+
for node in graph_data.get("nodes") or []:
|
| 689 |
+
if isinstance(node, dict) and isinstance(node.get("id"), str):
|
| 690 |
+
attrs = {k: v for k, v in node.items() if k not in {"id", "kind"}}
|
| 691 |
+
graph.add_node(node["id"], str(node.get("kind") or "unknown"), **attrs)
|
| 692 |
+
for edge in graph_data.get("edges") or []:
|
| 693 |
+
if isinstance(edge, dict):
|
| 694 |
+
graph.add_edge(str(edge.get("src") or ""),
|
| 695 |
+
str(edge.get("dst") or ""),
|
| 696 |
+
str(edge.get("kind") or "related"))
|
| 697 |
+
_GRAPH = graph
|
| 698 |
+
_BUILD_META = dict(meta)
|
| 699 |
+
_BUILD_META["generation_id"] = generation_id
|
| 700 |
+
_BUILD_META["generation_digest_sha256"] = actual_digest
|
| 701 |
+
_BUILD_META["integrity_state"] = "VERIFIED_ON_REHYDRATE"
|
| 702 |
+
_BUILD_META["corpus_chunk_count"] = counts["chunks"]
|
| 703 |
+
_BUILD_META["brain_handle_count"] = counts["brain_handles"]
|
| 704 |
+
_BUILD_META["training_authority_rows"] = 0
|
| 705 |
+
_BUILD_META["rehydrated_from_sqlite"] = True
|
| 706 |
+
_BUILD_META["rehydrated_at"] = time.time()
|
| 707 |
+
return True
|
| 708 |
+
except Exception as exc:
|
| 709 |
+
_BUILD_META = {
|
| 710 |
+
"built": False, "ts": None, "repos": 0, "chunks": 0,
|
| 711 |
+
"rehydration_state": "FAILED",
|
| 712 |
+
"rehydration_error_type": type(exc).__name__,
|
| 713 |
+
"honest_note": "persisted Brain state could not be rehydrated; rebuild required",
|
| 714 |
+
}
|
| 715 |
+
return False
|
| 716 |
+
|
| 717 |
+
|
| 718 |
# --------------------------------------------------------------------------- #
|
| 719 |
# GitHub enumeration (the offline build path). Receipted by the caller.
|
| 720 |
# --------------------------------------------------------------------------- #
|
|
|
|
| 793 |
graph = OrgGraph()
|
| 794 |
conn = _db()
|
| 795 |
has_fts5 = _init_schema(conn)
|
| 796 |
+
generation_id = _begin_generation(conn, "full-org")
|
|
|
|
| 797 |
|
| 798 |
if repos is None:
|
| 799 |
try:
|
|
|
|
| 852 |
cid = hashlib.sha256(f"{fid}:{j}".encode()).hexdigest()[:24]
|
| 853 |
csha = hashlib.sha256(seg.encode()).hexdigest()
|
| 854 |
conn.execute(
|
| 855 |
+
"INSERT INTO org_chunks_gen(generation_id,chunk_id,node_id,repo,path,kind,"
|
| 856 |
+
"corpus,source,title,body,sha256) VALUES(?,?,?,?,?,?,?,?,?,?,?)",
|
| 857 |
+
(generation_id, cid, fid, repo, path, "file", _cat,
|
| 858 |
+
f"gh:{ORG}/{repo}", path, seg, csha))
|
| 859 |
if embed_fn is not None:
|
| 860 |
try:
|
| 861 |
v = embed_fn(seg)
|
| 862 |
conn.execute(
|
| 863 |
+
"INSERT OR REPLACE INTO org_vectors_gen("
|
| 864 |
+
"generation_id,chunk_id,dim,vec) VALUES(?,?,?,?)",
|
| 865 |
+
(generation_id, cid, len(v),
|
| 866 |
+
json.dumps([round(x, 6) for x in v])))
|
| 867 |
except Exception:
|
| 868 |
pass
|
| 869 |
chunk_count += 1
|
| 870 |
conn.commit()
|
| 871 |
|
| 872 |
+
brain_handles = _ingest_brain_handles(conn, generation_id)
|
| 873 |
+
meta = {
|
| 874 |
+
"built": (chunk_count > 0 or brain_handles["count"] > 0),
|
| 875 |
+
"mode": "full", "ts": time.time(), "org": ORG,
|
| 876 |
"repos": len(repos), "chunks": chunk_count,
|
| 877 |
"fts5": has_fts5, "dense": embed_fn is not None,
|
| 878 |
"node_count": len(graph.nodes), "edge_count": len(graph.edges),
|
| 879 |
"build_ms": round((time.time() - t0) * 1000, 1),
|
| 880 |
"corpus_categories": sorted({_category_for(r) for r in repos}),
|
| 881 |
+
"brain_handle_plane": brain_handles,
|
| 882 |
"honest_note": ("dense vectors present" if embed_fn is not None
|
| 883 |
else "FTS5/lexical only — embedding model unavailable in this runtime (honest)"),
|
| 884 |
}
|
| 885 |
+
_persist_runtime_state(conn, graph, meta, generation_id)
|
| 886 |
conn.close()
|
| 887 |
+
rec = emit_receipt("org_rag.index.built", meta) if emit_receipt else None
|
| 888 |
+
out = {"ok": bool(meta.get("built")), **meta}
|
| 889 |
if rec:
|
| 890 |
out["khipu_hash"] = rec.get("hash")
|
| 891 |
return out
|
|
|
|
| 930 |
try:
|
| 931 |
conn = _db()
|
| 932 |
try:
|
| 933 |
+
_init_schema(conn)
|
| 934 |
+
generation_id = _active_generation(conn)
|
| 935 |
+
row = (conn.execute(
|
| 936 |
+
"SELECT COUNT(*) AS n FROM org_vectors_gen WHERE generation_id=?",
|
| 937 |
+
(generation_id,)).fetchone() if generation_id else
|
| 938 |
+
conn.execute("SELECT COUNT(*) AS n FROM org_vectors").fetchone())
|
| 939 |
return int(row["n"]) if row else 0
|
| 940 |
finally:
|
| 941 |
conn.close()
|
|
|
|
| 948 |
try:
|
| 949 |
conn = _db()
|
| 950 |
try:
|
| 951 |
+
_init_schema(conn)
|
| 952 |
+
generation_id = _active_generation(conn)
|
| 953 |
+
row = (conn.execute(
|
| 954 |
+
"SELECT COUNT(*) AS n FROM org_chunks_gen WHERE generation_id=?",
|
| 955 |
+
(generation_id,)).fetchone() if generation_id else
|
| 956 |
+
conn.execute("SELECT COUNT(*) AS n FROM org_chunks").fetchone())
|
| 957 |
return int(row["n"]) if row else 0
|
| 958 |
finally:
|
| 959 |
conn.close()
|
|
|
|
| 972 |
try:
|
| 973 |
conn = _db()
|
| 974 |
try:
|
| 975 |
+
_init_schema(conn)
|
| 976 |
+
generation_id = _active_generation(conn)
|
| 977 |
+
if generation_id:
|
| 978 |
+
rows = conn.execute(
|
| 979 |
+
"SELECT chunk_id,repo,path,corpus,source,body FROM org_chunks_gen "
|
| 980 |
+
"WHERE generation_id=? AND chunk_id NOT IN (SELECT chunk_id FROM "
|
| 981 |
+
"org_vectors_gen WHERE generation_id=?) LIMIT ?",
|
| 982 |
+
(generation_id, generation_id, max(1, int(limit)))).fetchall()
|
| 983 |
+
else:
|
| 984 |
+
rows = conn.execute(
|
| 985 |
+
"SELECT chunk_id,repo,path,corpus,source,body FROM org_chunks "
|
| 986 |
+
"WHERE chunk_id NOT IN (SELECT chunk_id FROM org_vectors) LIMIT ?",
|
| 987 |
+
(max(1, int(limit)),)).fetchall()
|
| 988 |
for r in rows:
|
| 989 |
out.append({"chunk_id": r["chunk_id"], "repo": r["repo"],
|
| 990 |
"path": r["path"], "corpus": r["corpus"],
|
|
|
|
| 1002 |
org_chunks — we never create a chunk row here, so an indexed chunk can never be
|
| 1003 |
fabricated. Returns {ok, chunk_id, dim} or an honest error. Uses the SAME
|
| 1004 |
storage format as _ingest_text (json list, 6-dp rounding)."""
|
| 1005 |
+
global _BUILD_META
|
| 1006 |
if not chunk_id or not isinstance(vec, (list, tuple)) or len(vec) == 0:
|
| 1007 |
return {"ok": False, "honest_error": "empty chunk_id or vector — nothing stored"}
|
| 1008 |
try:
|
| 1009 |
conn = _db()
|
| 1010 |
try:
|
| 1011 |
+
_init_schema(conn)
|
| 1012 |
+
generation_id = _active_generation(conn)
|
| 1013 |
+
exists = (conn.execute(
|
| 1014 |
+
"SELECT 1 FROM org_chunks_gen WHERE generation_id=? AND chunk_id=? LIMIT 1",
|
| 1015 |
+
(generation_id, chunk_id)).fetchone() if generation_id else
|
| 1016 |
+
conn.execute("SELECT 1 FROM org_chunks WHERE chunk_id=? LIMIT 1",
|
| 1017 |
+
(chunk_id,)).fetchone())
|
| 1018 |
if not exists:
|
| 1019 |
# Honest refusal: cannot add a vector for a chunk that was never
|
| 1020 |
# really ingested (would imply a fabricated indexed chunk).
|
|
|
|
| 1022 |
"honest_error": "chunk_id not present in org_chunks — refusing "
|
| 1023 |
"to store a vector for a non-existent chunk "
|
| 1024 |
"(Zero-Bandaid Law: never fabricate an index)"}
|
| 1025 |
+
if generation_id:
|
| 1026 |
+
# Vector useful-work is a bounded atomic augmentation: the vector,
|
| 1027 |
+
# generation digest, count, and metadata change in one transaction.
|
| 1028 |
+
# Readers see either the old snapshot or the fully sealed new one.
|
| 1029 |
+
with _SNAPSHOT_LOCK:
|
| 1030 |
+
conn.commit()
|
| 1031 |
+
conn.execute("BEGIN IMMEDIATE")
|
| 1032 |
+
conn.execute(
|
| 1033 |
+
"INSERT OR REPLACE INTO org_vectors_gen("
|
| 1034 |
+
"generation_id,chunk_id,dim,vec) VALUES(?,?,?,?)",
|
| 1035 |
+
(generation_id, chunk_id, len(vec),
|
| 1036 |
+
json.dumps([round(float(x), 6) for x in vec])))
|
| 1037 |
+
generation = conn.execute(
|
| 1038 |
+
"SELECT graph_json,meta_json FROM org_generations "
|
| 1039 |
+
"WHERE generation_id=? AND status='ACTIVE'", (generation_id,)
|
| 1040 |
+
).fetchone()
|
| 1041 |
+
if not generation:
|
| 1042 |
+
conn.rollback()
|
| 1043 |
+
raise RuntimeError("active generation disappeared during vector write")
|
| 1044 |
+
graph_data = json.loads(generation["graph_json"])
|
| 1045 |
+
meta = json.loads(generation["meta_json"])
|
| 1046 |
+
digest, counts = _generation_digest(conn, generation_id, graph_data)
|
| 1047 |
+
meta.update({
|
| 1048 |
+
"generation_digest_sha256": digest,
|
| 1049 |
+
"integrity_state": "VERIFIED_AFTER_ATOMIC_VECTOR_WRITE",
|
| 1050 |
+
})
|
| 1051 |
+
conn.execute(
|
| 1052 |
+
"UPDATE org_generations SET vector_count=?,digest_sha256=?,meta_json=? "
|
| 1053 |
+
"WHERE generation_id=? AND status='ACTIVE'",
|
| 1054 |
+
(counts["vectors"], digest, _canonical_json(meta), generation_id),
|
| 1055 |
+
)
|
| 1056 |
+
conn.commit()
|
| 1057 |
+
_BUILD_META = meta
|
| 1058 |
+
else:
|
| 1059 |
+
conn.execute(
|
| 1060 |
+
"INSERT OR REPLACE INTO org_vectors(chunk_id,dim,vec) VALUES(?,?,?)",
|
| 1061 |
+
(chunk_id, len(vec), json.dumps([round(float(x), 6) for x in vec])))
|
| 1062 |
+
conn.commit()
|
| 1063 |
finally:
|
| 1064 |
conn.close()
|
| 1065 |
except Exception as exc:
|
|
|
|
| 1248 |
|
| 1249 |
def _ingest_local_category(graph: OrgGraph, conn: sqlite3.Connection, *, category: str,
|
| 1250 |
local_dirs: list[str],
|
| 1251 |
+
embed_fn: Callable[[str], list[float]] | None,
|
| 1252 |
+
generation_id: str
|
| 1253 |
) -> tuple[int, int]:
|
| 1254 |
"""Ingest the REAL in-image mirror files for one category. Returns
|
| 1255 |
(files, chunks). Each chunk is labeled with an honest 'bundled:<repo>@<sha>'
|
|
|
|
| 1286 |
prov = _local_provenance(f"corpus/{rel}/{name}")
|
| 1287 |
wrote = _ingest_text(graph, conn, repo=prov["repo"], path=prov["path"],
|
| 1288 |
raw=raw, source=prov["source"], category=category,
|
| 1289 |
+
embed_fn=embed_fn, generation_id=generation_id)
|
| 1290 |
files_n += 1
|
| 1291 |
chunks_n += wrote
|
| 1292 |
return (files_n, chunks_n)
|
|
|
|
| 1294 |
|
| 1295 |
def _ingest_text(graph: OrgGraph, conn: sqlite3.Connection, *, repo: str, path: str,
|
| 1296 |
raw: str, source: str, category: str,
|
| 1297 |
+
embed_fn: Callable[[str], list[float]] | None,
|
| 1298 |
+
generation_id: str) -> int:
|
| 1299 |
"""Shared ingest: graph nodes/edges + symbols + imports + FTS5/vector chunks.
|
| 1300 |
Returns the number of chunks written. Used by seed AND full builds so the two
|
| 1301 |
paths are byte-for-byte consistent in how they ground + cite."""
|
|
|
|
| 1315 |
cid = hashlib.sha256(f"{source}:{fid}:{j}".encode()).hexdigest()[:24]
|
| 1316 |
csha = hashlib.sha256(seg.encode()).hexdigest()
|
| 1317 |
conn.execute(
|
| 1318 |
+
"INSERT INTO org_chunks_gen(generation_id,chunk_id,node_id,repo,path,kind,"
|
| 1319 |
+
"corpus,source,title,body,sha256) VALUES(?,?,?,?,?,?,?,?,?,?,?)",
|
| 1320 |
+
(generation_id, cid, fid, repo, path, "file", category, source, path, seg, csha))
|
| 1321 |
if embed_fn is not None:
|
| 1322 |
try:
|
| 1323 |
v = embed_fn(seg)
|
| 1324 |
conn.execute(
|
| 1325 |
+
"INSERT OR REPLACE INTO org_vectors_gen(generation_id,chunk_id,dim,vec) "
|
| 1326 |
+
"VALUES(?,?,?,?)",
|
| 1327 |
+
(generation_id, cid, len(v), json.dumps([round(x, 6) for x in v])))
|
| 1328 |
except Exception:
|
| 1329 |
pass
|
| 1330 |
n += 1
|
|
|
|
| 1343 |
graph = OrgGraph()
|
| 1344 |
conn = _db()
|
| 1345 |
has_fts5 = _init_schema(conn)
|
| 1346 |
+
generation_id = _begin_generation(conn, "seed")
|
|
|
|
| 1347 |
embed_fn = _maybe_embedder()
|
| 1348 |
per_cat: dict[str, dict[str, int]] = {}
|
| 1349 |
chunk_count = 0
|
|
|
|
| 1375 |
continue
|
| 1376 |
repo_for = src.split("/")[-1]
|
| 1377 |
wrote = _ingest_text(graph, conn, repo=repo_for, path=path, raw=raw,
|
| 1378 |
+
source=src, category=cat, embed_fn=embed_fn,
|
| 1379 |
+
generation_id=generation_id)
|
| 1380 |
c_files += 1
|
| 1381 |
c_chunks += wrote
|
| 1382 |
chunk_count += wrote
|
|
|
|
| 1387 |
local_dirs = spec.get("local_paths", [])
|
| 1388 |
if c_files == 0 and local_dirs:
|
| 1389 |
lf, lc = _ingest_local_category(graph, conn, category=cat,
|
| 1390 |
+
local_dirs=local_dirs, embed_fn=embed_fn,
|
| 1391 |
+
generation_id=generation_id)
|
| 1392 |
c_files += lf
|
| 1393 |
c_chunks += lc
|
| 1394 |
chunk_count += lc
|
|
|
|
| 1396 |
per_cat[cat] = {"files": c_files, "chunks": c_chunks}
|
| 1397 |
conn.commit()
|
| 1398 |
|
| 1399 |
+
brain_handles = _ingest_brain_handles(conn, generation_id)
|
| 1400 |
+
meta = {
|
| 1401 |
+
"built": (chunk_count > 0 or brain_handles["count"] > 0),
|
| 1402 |
+
"mode": "seed", "ts": time.time(), "org": ORG,
|
| 1403 |
"repos": len({s for s in per_cat}), "chunks": chunk_count, "files": files_ok,
|
| 1404 |
"fts5": has_fts5, "dense": embed_fn is not None,
|
| 1405 |
"node_count": len(graph.nodes), "edge_count": len(graph.edges),
|
| 1406 |
"build_ms": round((time.time() - t0) * 1000, 1),
|
| 1407 |
"per_category": per_cat,
|
| 1408 |
+
"brain_handle_plane": brain_handles,
|
| 1409 |
"corpus_categories": [c for c, v in per_cat.items() if v["chunks"] > 0],
|
| 1410 |
"gh_credential": bool(gh), "hf_credential": bool(hf),
|
| 1411 |
"honest_note": (
|
|
|
|
| 1418 |
"szl-holdings repos read UNAUTHENTICATED (rate-limited but real); "
|
| 1419 |
"HF Spaces also ingested (honest, not fabricated).")),
|
| 1420 |
}
|
| 1421 |
+
_persist_runtime_state(conn, graph, meta, generation_id)
|
| 1422 |
conn.close()
|
| 1423 |
+
rec = emit_receipt("org_rag.index.seed", meta) if emit_receipt else None
|
| 1424 |
+
out = {"ok": meta["built"], **meta}
|
| 1425 |
+
if not meta["built"]:
|
| 1426 |
out["honest_error"] = ("seed index empty — no corpus file could be fetched "
|
| 1427 |
"(no GitHub/HF credential reachable). NOT claiming a "
|
| 1428 |
"built index (Zero-Bandaid Law).")
|
|
|
|
| 1445 |
graph = OrgGraph()
|
| 1446 |
conn = _db()
|
| 1447 |
has_fts5 = _init_schema(conn)
|
| 1448 |
+
generation_id = _begin_generation(conn, "full")
|
|
|
|
| 1449 |
embed_fn = _maybe_embedder()
|
| 1450 |
per_cat: dict[str, dict[str, int]] = {}
|
| 1451 |
chunk_count = 0
|
|
|
|
| 1486 |
continue
|
| 1487 |
wrote = _ingest_text(graph, conn, repo=repo, path=f["path"],
|
| 1488 |
raw=raw, source=f"gh:{ORG}/{repo}",
|
| 1489 |
+
category=cat, embed_fn=embed_fn,
|
| 1490 |
+
generation_id=generation_id)
|
| 1491 |
c_files += 1
|
| 1492 |
c_chunks += wrote
|
| 1493 |
chunk_count += wrote
|
|
|
|
| 1501 |
continue
|
| 1502 |
wrote = _ingest_text(graph, conn, repo=sp, path=path, raw=raw,
|
| 1503 |
source=f"hf:{HF_ORG}/{sp}", category=cat,
|
| 1504 |
+
embed_fn=embed_fn,
|
| 1505 |
+
generation_id=generation_id)
|
| 1506 |
c_files += 1
|
| 1507 |
c_chunks += wrote
|
| 1508 |
chunk_count += wrote
|
|
|
|
| 1515 |
local_dirs = spec.get("local_paths", [])
|
| 1516 |
if c_files == 0 and local_dirs:
|
| 1517 |
lf, lc = _ingest_local_category(graph, conn, category=cat,
|
| 1518 |
+
local_dirs=local_dirs, embed_fn=embed_fn,
|
| 1519 |
+
generation_id=generation_id)
|
| 1520 |
c_files += lf
|
| 1521 |
c_chunks += lc
|
| 1522 |
chunk_count += lc
|
|
|
|
| 1527 |
"category": cat, "files": c_files, "chunks": c_chunks})
|
| 1528 |
|
| 1529 |
built_cats = [c for c, v in per_cat.items() if v["chunks"] > 0]
|
| 1530 |
+
brain_handles = _ingest_brain_handles(conn, generation_id)
|
| 1531 |
+
meta = {
|
| 1532 |
+
"built": (chunk_count > 0 or brain_handles["count"] > 0),
|
| 1533 |
+
"mode": "full", "ts": time.time(), "org": ORG,
|
| 1534 |
"repos": len(seen_repo), "chunks": chunk_count,
|
| 1535 |
"fts5": has_fts5, "dense": embed_fn is not None,
|
| 1536 |
"node_count": len(graph.nodes), "edge_count": len(graph.edges),
|
| 1537 |
"build_ms": round((time.time() - t0) * 1000, 1),
|
| 1538 |
"per_category": per_cat, "corpus_categories": built_cats,
|
| 1539 |
+
"brain_handle_plane": brain_handles,
|
| 1540 |
"gh_credential": bool(gh),
|
| 1541 |
"corpus_mirror": bool(_corpus_root()),
|
| 1542 |
"honest_note": (
|
|
|
|
| 1552 |
"source='bundled:<repo>@<commit_sha>:<path>' — real files, honest "
|
| 1553 |
"provenance, NOT fabricated." if _corpus_root() else "")),
|
| 1554 |
}
|
| 1555 |
+
_persist_runtime_state(conn, graph, meta, generation_id)
|
| 1556 |
conn.close()
|
| 1557 |
+
rec = emit_receipt("org_rag.index.full", meta) if emit_receipt else None
|
| 1558 |
+
out = {"ok": meta["built"], **meta}
|
| 1559 |
if rec:
|
| 1560 |
out["khipu_hash"] = rec.get("hash")
|
| 1561 |
return out
|
|
|
|
| 1649 |
``file{path,sha256}`` evidence, plus an ``i_dont_know`` flag when support is
|
| 1650 |
too low. ``hyde_text`` (optional) is a hypothetical answer used for dense
|
| 1651 |
recall (HyDE) instead of the bare query."""
|
| 1652 |
+
_rehydrate_runtime_state()
|
| 1653 |
if not _BUILD_META.get("built"):
|
| 1654 |
return {"ok": False, "i_dont_know": True,
|
| 1655 |
"honest_error": "org index not built — call /api/a11oy/code/rag/index first",
|
| 1656 |
"query": q, "chunks": []}
|
| 1657 |
+
with _SNAPSHOT_LOCK:
|
| 1658 |
+
conn = _db()
|
| 1659 |
+
_init_schema(conn)
|
| 1660 |
+
conn.execute("BEGIN")
|
| 1661 |
+
generation_id = _active_generation(conn)
|
| 1662 |
+
graph_snapshot = _GRAPH
|
| 1663 |
+
meta_snapshot = dict(_BUILD_META)
|
| 1664 |
+
if generation_id and generation_id != meta_snapshot.get("generation_id"):
|
| 1665 |
+
conn.close()
|
| 1666 |
+
return {"ok": False, "i_dont_know": True, "query": q, "chunks": [],
|
| 1667 |
+
"honest_error": "Brain generation/graph snapshot mismatch; retry after rebuild",
|
| 1668 |
+
"integrity_state": "FAILED_CLOSED"}
|
| 1669 |
embed_fn = _maybe_embedder()
|
| 1670 |
recall_text = hyde_text or q
|
| 1671 |
# Stage 1: lexical recall (FTS5 or LIKE fallback).
|
| 1672 |
+
rows: list[dict[str, Any]] = []
|
| 1673 |
try:
|
| 1674 |
+
if generation_id:
|
| 1675 |
+
sql = ("SELECT chunk_id,node_id,repo,path,corpus,source,title,body,sha256 "
|
| 1676 |
+
"FROM org_chunks_gen WHERE org_chunks_gen MATCH ? AND generation_id=?")
|
| 1677 |
+
args: list[Any] = [_fts_escape(q), generation_id]
|
| 1678 |
+
else:
|
| 1679 |
+
sql = ("SELECT chunk_id,node_id,repo,path,corpus,source,title,body,sha256 "
|
| 1680 |
+
"FROM org_chunks WHERE org_chunks MATCH ?")
|
| 1681 |
+
args = [_fts_escape(q)]
|
| 1682 |
if repo:
|
| 1683 |
sql += " AND repo = ?"
|
| 1684 |
args.append(repo)
|
| 1685 |
sql += " LIMIT ?"
|
| 1686 |
args.append(max(k * 4, 24))
|
| 1687 |
+
rows = [{**dict(row), "retrieval_plane": "corpus"}
|
| 1688 |
+
for row in conn.execute(sql, args)]
|
| 1689 |
except Exception:
|
| 1690 |
# LIKE fallback (non-FTS5 runtime) — labeled weaker.
|
| 1691 |
like = f"%{re.sub(r'[^A-Za-z0-9_ ]', ' ', q)[:60]}%"
|
| 1692 |
+
if generation_id:
|
| 1693 |
+
sql = ("SELECT chunk_id,node_id,repo,path,corpus,source,title,body,sha256 "
|
| 1694 |
+
"FROM org_chunks_gen WHERE generation_id=? AND body LIKE ?")
|
| 1695 |
+
args = [generation_id, like]
|
| 1696 |
+
else:
|
| 1697 |
+
sql = ("SELECT chunk_id,node_id,repo,path,corpus,source,title,body,sha256 "
|
| 1698 |
+
"FROM org_chunks WHERE body LIKE ?")
|
| 1699 |
+
args = [like]
|
| 1700 |
if repo:
|
| 1701 |
sql += " AND repo = ?"
|
| 1702 |
args.append(repo)
|
| 1703 |
sql += " LIMIT ?"
|
| 1704 |
args.append(max(k * 4, 24))
|
| 1705 |
try:
|
| 1706 |
+
rows = [{**dict(row), "retrieval_plane": "corpus"}
|
| 1707 |
+
for row in conn.execute(sql, args)]
|
| 1708 |
except Exception:
|
| 1709 |
rows = []
|
| 1710 |
|
| 1711 |
+
# Search the M1 decision ledger as a distinct retrieval-only plane. These
|
| 1712 |
+
# rows are metadata handles (title/kind/source/URL/receipt/safety), not copied
|
| 1713 |
+
# external documents, and never grant gradient or training authority.
|
| 1714 |
+
if generation_id and (repo is None or repo == "m1-brain-ledger"):
|
| 1715 |
+
handle_rows: list[sqlite3.Row] = []
|
| 1716 |
+
try:
|
| 1717 |
+
handle_rows = list(conn.execute(
|
| 1718 |
+
"SELECT handle_id,node_id,source,source_url,receipt_id,safety_decision,"
|
| 1719 |
+
"training_decision,source_training_eligible,title,metadata_text "
|
| 1720 |
+
"FROM org_brain_handles_gen WHERE org_brain_handles_gen MATCH ? "
|
| 1721 |
+
"AND generation_id=? LIMIT ?",
|
| 1722 |
+
(_fts_escape(q), generation_id, max(k * 4, 24))))
|
| 1723 |
+
except Exception:
|
| 1724 |
+
like = f"%{re.sub(r'[^A-Za-z0-9_ ]', ' ', q)[:60]}%"
|
| 1725 |
+
try:
|
| 1726 |
+
handle_rows = list(conn.execute(
|
| 1727 |
+
"SELECT handle_id,node_id,source,source_url,receipt_id,safety_decision,"
|
| 1728 |
+
"training_decision,source_training_eligible,title,metadata_text "
|
| 1729 |
+
"FROM org_brain_handles_gen WHERE generation_id=? AND metadata_text LIKE ? "
|
| 1730 |
+
"LIMIT ?", (generation_id, like, max(k * 4, 24))))
|
| 1731 |
+
except Exception:
|
| 1732 |
+
handle_rows = []
|
| 1733 |
+
for handle_row in handle_rows:
|
| 1734 |
+
item = dict(handle_row)
|
| 1735 |
+
rows.append({
|
| 1736 |
+
"chunk_id": item["handle_id"], "node_id": item["node_id"],
|
| 1737 |
+
"repo": "m1-brain-ledger", "path": f"brain-handle/{item['node_id']}",
|
| 1738 |
+
"corpus": "brain_handles", "source": item["source"],
|
| 1739 |
+
"title": item["title"], "body": item["metadata_text"],
|
| 1740 |
+
"sha256": item["handle_id"], "retrieval_plane": "brain_handle",
|
| 1741 |
+
"source_url": item["source_url"], "receipt_id": item["receipt_id"],
|
| 1742 |
+
"safety_decision": item["safety_decision"],
|
| 1743 |
+
"training_decision": item["training_decision"],
|
| 1744 |
+
"source_training_eligible": item["source_training_eligible"],
|
| 1745 |
+
})
|
| 1746 |
+
|
| 1747 |
# dense vector for query (HyDE-aware)
|
| 1748 |
qvec = None
|
| 1749 |
if embed_fn is not None:
|
|
|
|
| 1761 |
lexical = (len(qtokens & btokens) / (len(qtokens) + 1e-9)) if qtokens else 0.0
|
| 1762 |
lexical = min(1.0, lexical)
|
| 1763 |
semantic = lexical
|
| 1764 |
+
if qvec is not None and r["retrieval_plane"] == "corpus":
|
| 1765 |
+
row = (conn.execute(
|
| 1766 |
+
"SELECT vec FROM org_vectors_gen WHERE generation_id=? AND chunk_id=?",
|
| 1767 |
+
(generation_id, r["chunk_id"])).fetchone() if generation_id else
|
| 1768 |
+
conn.execute("SELECT vec FROM org_vectors WHERE chunk_id=?",
|
| 1769 |
+
(r["chunk_id"],)).fetchone())
|
| 1770 |
if row:
|
| 1771 |
try:
|
| 1772 |
semantic = max(0.0, _cosine(qvec, json.loads(row["vec"])))
|
| 1773 |
except Exception:
|
| 1774 |
pass
|
| 1775 |
+
centrality = graph_snapshot.centrality(r["node_id"])
|
| 1776 |
# conformal anti-overconfidence floor 1/(n+1) over the recall set.
|
| 1777 |
conformal = 1.0 - 1.0 / (len(rows) + 1)
|
| 1778 |
# Λ over the three relevance axes (geometric mean — never 1.0 unless all 1.0).
|
|
|
|
| 1780 |
_cols = r.keys()
|
| 1781 |
corpus = (r["corpus"] if "corpus" in _cols else None) or _category_for(r["repo"])
|
| 1782 |
source = (r["source"] if "source" in _cols else None) or f"gh:{ORG}/{r['repo']}"
|
| 1783 |
+
scored_item = {
|
| 1784 |
"chunk_id": r["chunk_id"], "node_id": r["node_id"], "repo": r["repo"],
|
| 1785 |
"path": r["path"], "title": r["title"], "text": body[:1200],
|
| 1786 |
"sha256": r["sha256"], "corpus": corpus, "source": source,
|
| 1787 |
"scores": {"semantic": round(semantic, 4), "lexical": round(lexical, 4),
|
| 1788 |
"centrality": round(centrality, 4), "conformal": round(conformal, 4)},
|
| 1789 |
"lambda": round(lam, 4),
|
| 1790 |
+
"retrieval_plane": r["retrieval_plane"],
|
| 1791 |
# M2M evidence of kind file{path,sha256} — carries corpus+source so the
|
| 1792 |
# agent CITES exactly where each grounded claim came from (founder mandate).
|
| 1793 |
"evidence": {"kind": "file", "path": f"{r['repo']}/{r['path']}",
|
| 1794 |
"sha256": r["sha256"], "corpus": corpus, "source": source,
|
| 1795 |
"citation": f"{source}/{r['path']}"},
|
| 1796 |
+
}
|
| 1797 |
+
if r["retrieval_plane"] == "brain_handle":
|
| 1798 |
+
scored_item["evidence"] = {
|
| 1799 |
+
"kind": "brain_handle", "node_id": r["node_id"],
|
| 1800 |
+
"handle_sha256": r["sha256"], "source": source,
|
| 1801 |
+
"source_url": r.get("source_url"), "receipt_id": r.get("receipt_id"),
|
| 1802 |
+
"safety_decision": r.get("safety_decision"),
|
| 1803 |
+
"training_decision": r.get("training_decision"),
|
| 1804 |
+
"retrieval_only": True, "gradient_authority": False,
|
| 1805 |
+
"citation": r.get("source_url") or r.get("receipt_id"),
|
| 1806 |
+
}
|
| 1807 |
+
scored_item["training_authority"] = "NONE"
|
| 1808 |
+
scored.append(scored_item)
|
| 1809 |
conn.close()
|
| 1810 |
scored.sort(key=lambda x: x["lambda"], reverse=True)
|
| 1811 |
grounded = [s for s in scored if s["lambda"] >= _LAMBDA_FLOOR][:k]
|
| 1812 |
i_dont_know = len(grounded) == 0
|
| 1813 |
+
evidence_set = [
|
| 1814 |
+
{
|
| 1815 |
+
"rank": rank,
|
| 1816 |
+
"chunk_id": item.get("chunk_id"),
|
| 1817 |
+
"node_id": item.get("node_id"),
|
| 1818 |
+
"repo": item.get("repo"),
|
| 1819 |
+
"path": item.get("path"),
|
| 1820 |
+
"sha256": item.get("sha256"),
|
| 1821 |
+
"corpus": item.get("corpus"),
|
| 1822 |
+
"source": item.get("source"),
|
| 1823 |
+
"lambda": item.get("lambda"),
|
| 1824 |
+
}
|
| 1825 |
+
for rank, item in enumerate(grounded, start=1)
|
| 1826 |
+
]
|
| 1827 |
+
evidence_set_sha256 = hashlib.sha256(json.dumps(
|
| 1828 |
+
evidence_set, sort_keys=True, separators=(",", ":"),
|
| 1829 |
+
ensure_ascii=False).encode("utf-8")).hexdigest()
|
| 1830 |
out = {
|
| 1831 |
"ok": True,
|
| 1832 |
"query": q,
|
|
|
|
| 1835 |
"lambda_floor": _LAMBDA_FLOOR,
|
| 1836 |
"recall_count": len(scored),
|
| 1837 |
"grounded_count": len(grounded),
|
| 1838 |
+
"generation_id": generation_id,
|
| 1839 |
+
"generation_digest_sha256": meta_snapshot.get("generation_digest_sha256"),
|
| 1840 |
+
"recall_by_plane": {
|
| 1841 |
+
"corpus": sum(1 for s in scored if s["retrieval_plane"] == "corpus"),
|
| 1842 |
+
"brain_handles": sum(1 for s in scored if s["retrieval_plane"] == "brain_handle"),
|
| 1843 |
+
},
|
| 1844 |
+
"brain_handle_count": int(meta_snapshot.get("brain_handle_count") or 0),
|
| 1845 |
+
"training_authority_rows": 0,
|
| 1846 |
"i_dont_know": i_dont_know,
|
| 1847 |
"chunks": grounded,
|
| 1848 |
+
"evidence_set": evidence_set,
|
| 1849 |
+
"evidence_set_sha256": evidence_set_sha256,
|
| 1850 |
"honest_note": ("no chunk cleared the Λ relevance floor — returning i_dont_know "
|
| 1851 |
"rather than fabricating support (Self-RAG)") if i_dont_know else None,
|
| 1852 |
}
|
| 1853 |
if emit_receipt:
|
| 1854 |
rec = emit_receipt("org_rag.query", {
|
| 1855 |
"query": q[:120], "grounded": len(grounded), "i_dont_know": i_dont_know,
|
| 1856 |
+
"dense": qvec is not None,
|
| 1857 |
+
"evidence_set_sha256": evidence_set_sha256})
|
| 1858 |
out["khipu_hash"] = rec.get("hash")
|
| 1859 |
return out
|
| 1860 |
|
| 1861 |
|
| 1862 |
def repo_map(repo: str) -> dict[str, Any]:
|
| 1863 |
"""Aider-style repo map: files → symbols, ranked by Λ-weighted graph centrality."""
|
| 1864 |
+
_rehydrate_runtime_state()
|
| 1865 |
if not _BUILD_META.get("built"):
|
| 1866 |
return {"ok": False, "honest_error": "org index not built — call build_index first",
|
| 1867 |
"repo": repo}
|
|
|
|
| 1879 |
|
| 1880 |
def graph_dict() -> dict[str, Any]:
|
| 1881 |
"""Org graph for the 3D UI (nodes/edges). Honest empty state if not built."""
|
| 1882 |
+
_rehydrate_runtime_state()
|
| 1883 |
d = _GRAPH.to_dict()
|
| 1884 |
d["built"] = _BUILD_META.get("built", False)
|
| 1885 |
d["meta"] = _BUILD_META
|
|
|
|
| 1887 |
|
| 1888 |
|
| 1889 |
def status() -> dict[str, Any]:
|
| 1890 |
+
_rehydrate_runtime_state()
|
| 1891 |
+
handle_plane = dict(_BUILD_META.get("brain_handle_plane") or {})
|
| 1892 |
+
handle_plane.setdefault("state", "NOT_INDEXED")
|
| 1893 |
+
handle_plane.setdefault("count", int(_BUILD_META.get("brain_handle_count") or 0))
|
| 1894 |
+
handle_plane["gradient_authority_rows"] = 0
|
| 1895 |
+
handle_plane["training_authority"] = "NONE"
|
| 1896 |
return {"ok": True, **_BUILD_META, "db_path": RAG_DB_PATH,
|
| 1897 |
"lambda_floor": _LAMBDA_FLOOR,
|
| 1898 |
+
"brain_handle_plane": handle_plane,
|
| 1899 |
+
"corpus_chunk_count": int(_BUILD_META.get("corpus_chunk_count") or 0),
|
| 1900 |
+
"brain_handle_count": int(_BUILD_META.get("brain_handle_count") or 0),
|
| 1901 |
+
"training_authority_rows": 0,
|
| 1902 |
"corpus": corpus_manifest(),
|
| 1903 |
"build_state": build_state()}
|
| 1904 |
|
|
|
|
| 1944 |
return {"ok": False, "honest_error": f"szl_waqay unavailable: {e}", "label": "WAQAY"}
|
| 1945 |
conn = _db()
|
| 1946 |
try:
|
| 1947 |
+
_init_schema(conn)
|
| 1948 |
+
generation_id = _active_generation(conn)
|
| 1949 |
+
rows = list(conn.execute(
|
| 1950 |
+
"SELECT chunk_id,dim,vec FROM org_vectors_gen WHERE generation_id=?",
|
| 1951 |
+
(generation_id,))) if generation_id else list(
|
| 1952 |
+
conn.execute("SELECT chunk_id,dim,vec FROM org_vectors"))
|
| 1953 |
except Exception as e:
|
| 1954 |
+
conn.close()
|
| 1955 |
return {"ok": False, "honest_error": f"org_vectors unavailable: {e}", "label": "WAQAY"}
|
| 1956 |
+
conn.close()
|
| 1957 |
if not rows:
|
| 1958 |
return {"ok": False, "honest_error": "no dense vectors in org_vectors "
|
| 1959 |
"(FTS5-only runtime) — WAQAY needs an embedding model present",
|
|
|
|
| 1978 |
_WAQAY_INDEX = idx
|
| 1979 |
comp = idx.compression()
|
| 1980 |
_WAQAY_META = {"built": True, "n": len(ids), "dim": dim, "bit_width": bit_width,
|
| 1981 |
+
"generation_id": generation_id,
|
| 1982 |
"compression_MEASURED": comp,
|
| 1983 |
"recall_MODELED": szl_waqay.WaqayIndex.modeled_recall_bound(bit_width),
|
| 1984 |
"label": "WAQAY"}
|
|
|
|
| 2007 |
return {"ok": False, "honest_error": f"szl_waqay unavailable: {e}",
|
| 2008 |
"fallback": query(q, k=k, repo=repo, hyde_text=hyde_text,
|
| 2009 |
emit_receipt=emit_receipt)}
|
| 2010 |
+
active_generation = _BUILD_META.get("generation_id")
|
| 2011 |
+
if (_WAQAY_INDEX is None or not _WAQAY_META.get("built")
|
| 2012 |
+
or _WAQAY_META.get("generation_id") != active_generation):
|
| 2013 |
b = build_waqay_backend(emit_receipt=emit_receipt)
|
| 2014 |
if not b.get("ok"):
|
| 2015 |
# honest fallback to exact path — opting in never costs recall.
|
|
|
|
| 2028 |
allow=allow, data_label="LIVE")
|
| 2029 |
# Hydrate returned chunk ids with their text from org_chunks.
|
| 2030 |
conn = _db()
|
| 2031 |
+
_init_schema(conn)
|
| 2032 |
+
generation_id = _active_generation(conn)
|
| 2033 |
chunks = []
|
| 2034 |
for item in gres.get("results", []):
|
| 2035 |
cid = item["id"]
|
| 2036 |
try:
|
| 2037 |
+
row = (conn.execute(
|
| 2038 |
+
"SELECT chunk_id,repo,path,corpus,source,title,body,sha256 "
|
| 2039 |
+
"FROM org_chunks_gen WHERE generation_id=? AND chunk_id=?",
|
| 2040 |
+
(generation_id, cid)).fetchone() if generation_id else
|
| 2041 |
+
conn.execute("SELECT chunk_id,repo,path,corpus,source,title,body,sha256 "
|
| 2042 |
+
"FROM org_chunks WHERE chunk_id=?", (cid,)).fetchone())
|
| 2043 |
except Exception:
|
| 2044 |
row = None
|
| 2045 |
if row is not None:
|
|
|
|
| 2050 |
"evidence": {"file": {"path": row["path"], "sha256": row["sha256"]}}})
|
| 2051 |
else:
|
| 2052 |
chunks.append({"chunk_id": cid, "score_approx": item["score"]})
|
| 2053 |
+
conn.close()
|
| 2054 |
if emit_receipt:
|
| 2055 |
emit_receipt("org_rag.waqay.query", {"query": q[:120], "k": k,
|
| 2056 |
"returned": [c["chunk_id"] for c in chunks]})
|
|
@@ -5,9 +5,10 @@ agent-personas sharing one guarded tool loop, an always-on daemon, an autonomy g
|
|
| 5 |
and a collaboration lounge) and rebuilds it in a11oy's idiom: the active-flux model
|
| 6 |
router, the bounded-autonomy AgentLoop, and DSSE receipts.
|
| 7 |
|
| 8 |
-
It deliberately does NOT adopt the tribe's "fully agentic, no sandbox" mandate.
|
| 9 |
-
|
| 10 |
-
|
|
|
|
| 11 |
|
| 12 |
Public surface:
|
| 13 |
from ayllu.personas import ROSTER, get_persona, load_soul
|
|
@@ -18,7 +19,7 @@ Public surface:
|
|
| 18 |
"""
|
| 19 |
from __future__ import annotations
|
| 20 |
|
| 21 |
-
__version__ = "0.
|
| 22 |
NAMESPACE_DEFAULT = "a11oy"
|
| 23 |
|
| 24 |
__all__ = ["__version__", "NAMESPACE_DEFAULT"]
|
|
|
|
| 5 |
and a collaboration lounge) and rebuilds it in a11oy's idiom: the active-flux model
|
| 6 |
router, the bounded-autonomy AgentLoop, and DSSE receipts.
|
| 7 |
|
| 8 |
+
It deliberately does NOT adopt the tribe's "fully agentic, no sandbox" mandate.
|
| 9 |
+
The current runtime performs bounded direct completions with no tool dispatch. A
|
| 10 |
+
separate autonomy gate exists for a future approved tool loop, but it is not claimed
|
| 11 |
+
as active. See INGEST.md for the full mapping and boundary.
|
| 12 |
|
| 13 |
Public surface:
|
| 14 |
from ayllu.personas import ROSTER, get_persona, load_soul
|
|
|
|
| 19 |
"""
|
| 20 |
from __future__ import annotations
|
| 21 |
|
| 22 |
+
__version__ = "0.3.0"
|
| 23 |
NAMESPACE_DEFAULT = "a11oy"
|
| 24 |
|
| 25 |
__all__ = ["__version__", "NAMESPACE_DEFAULT"]
|
|
@@ -3,9 +3,9 @@
|
|
| 3 |
Honest wiring: ayllu never talks to a provider directly. It delegates to
|
| 4 |
`a11oy_code_orchestrator.agent_model_complete`, which owns model routing (route()),
|
| 5 |
resilient fallback, and per-completion energy receipts, and which returns a
|
| 6 |
-
CLEARLY-LABELED deterministic stub (never a fabricated answer) when
|
| 7 |
-
|
| 8 |
-
|
| 9 |
|
| 10 |
Each turn is wrapped in an a11oy OTel span (szl_observability.span) when present.
|
| 11 |
Everything here is guarded: if a11oy's modules are absent, model_complete returns an
|
|
@@ -15,6 +15,8 @@ from __future__ import annotations
|
|
| 15 |
|
| 16 |
import asyncio
|
| 17 |
import contextlib
|
|
|
|
|
|
|
| 18 |
from typing import Any, Optional
|
| 19 |
|
| 20 |
|
|
@@ -48,11 +50,21 @@ def backend_status() -> dict[str, Any]:
|
|
| 48 |
has_cred = bool(orch._resolve_hf_token()) or any(
|
| 49 |
orch._resolve_provider_keys().values())
|
| 50 |
_base, local_ready = orch._serving_base()
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
cred_checked = True
|
| 53 |
except Exception:
|
| 54 |
cred_checked = False
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
if orch is None:
|
| 57 |
mode = "unavailable"
|
| 58 |
elif not cred_checked:
|
|
@@ -81,6 +93,7 @@ def backend_status() -> dict[str, Any]:
|
|
| 81 |
"clearly-labeled deterministic stub, no fabrication."),
|
| 82 |
}.get(mode, ""),
|
| 83 |
"backend": "a11oy_code_orchestrator.agent_model_complete",
|
|
|
|
| 84 |
}
|
| 85 |
|
| 86 |
|
|
@@ -117,10 +130,63 @@ async def model_complete(
|
|
| 117 |
}
|
| 118 |
bounded_tokens = max(1, min(int(max_tokens), 2048))
|
| 119 |
bounded_timeout = max(0.1, min(float(timeout_s), 120.0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
try:
|
| 121 |
result = await asyncio.wait_for(
|
| 122 |
_o.agent_model_complete(
|
| 123 |
-
messages, max_tokens=bounded_tokens, temperature=temperature
|
|
|
|
| 124 |
timeout=bounded_timeout,
|
| 125 |
)
|
| 126 |
except asyncio.TimeoutError:
|
|
@@ -159,8 +225,79 @@ async def model_complete(
|
|
| 159 |
"timeout_s": bounded_timeout,
|
| 160 |
"honesty": "model backend returned a non-contract value; no answer was used",
|
| 161 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
return {
|
| 163 |
-
"text":
|
| 164 |
"model": result.get("model"),
|
| 165 |
"stub": bool(result.get("stub")),
|
| 166 |
"timeout": bool(result.get("timeout", False)),
|
|
@@ -168,4 +305,6 @@ async def model_complete(
|
|
| 168 |
"timeout_s": bounded_timeout,
|
| 169 |
"honesty": result.get("honesty"),
|
| 170 |
"energy_receipt": result.get("energy_receipt"),
|
|
|
|
|
|
|
| 171 |
}
|
|
|
|
| 3 |
Honest wiring: ayllu never talks to a provider directly. It delegates to
|
| 4 |
`a11oy_code_orchestrator.agent_model_complete`, which owns model routing (route()),
|
| 5 |
resilient fallback, and per-completion energy receipts, and which returns a
|
| 6 |
+
CLEARLY-LABELED deterministic stub (never a fabricated answer) when neither a
|
| 7 |
+
reachable local endpoint nor a credentialed remote provider is available. The
|
| 8 |
+
live/stub decision is a11oy's, resolved at RUNTIME with no redeploy.
|
| 9 |
|
| 10 |
Each turn is wrapped in an a11oy OTel span (szl_observability.span) when present.
|
| 11 |
Everything here is guarded: if a11oy's modules are absent, model_complete returns an
|
|
|
|
| 15 |
|
| 16 |
import asyncio
|
| 17 |
import contextlib
|
| 18 |
+
import hashlib
|
| 19 |
+
import json
|
| 20 |
from typing import Any, Optional
|
| 21 |
|
| 22 |
|
|
|
|
| 50 |
has_cred = bool(orch._resolve_hf_token()) or any(
|
| 51 |
orch._resolve_provider_keys().values())
|
| 52 |
_base, local_ready = orch._serving_base()
|
| 53 |
+
readiness = getattr(orch, "inference_backend_ready", None)
|
| 54 |
+
backend_ready = bool(readiness() if callable(readiness)
|
| 55 |
+
else orch.has_inference_credential() or local_ready)
|
| 56 |
cred_checked = True
|
| 57 |
except Exception:
|
| 58 |
cred_checked = False
|
| 59 |
|
| 60 |
+
profile_runtime = None
|
| 61 |
+
if orch is not None:
|
| 62 |
+
try:
|
| 63 |
+
profile_status = getattr(orch, "forge_profile_runtime_status", None)
|
| 64 |
+
profile_runtime = profile_status() if callable(profile_status) else None
|
| 65 |
+
except Exception:
|
| 66 |
+
profile_runtime = None
|
| 67 |
+
|
| 68 |
if orch is None:
|
| 69 |
mode = "unavailable"
|
| 70 |
elif not cred_checked:
|
|
|
|
| 93 |
"clearly-labeled deterministic stub, no fabrication."),
|
| 94 |
}.get(mode, ""),
|
| 95 |
"backend": "a11oy_code_orchestrator.agent_model_complete",
|
| 96 |
+
"forge_profiles": profile_runtime,
|
| 97 |
}
|
| 98 |
|
| 99 |
|
|
|
|
| 130 |
}
|
| 131 |
bounded_tokens = max(1, min(int(max_tokens), 2048))
|
| 132 |
bounded_timeout = max(0.1, min(float(timeout_s), 120.0))
|
| 133 |
+
profile = None
|
| 134 |
+
try:
|
| 135 |
+
from .model_binding import persona_binding
|
| 136 |
+
|
| 137 |
+
profile = persona_binding(persona or "")["primary_profile"]
|
| 138 |
+
except Exception:
|
| 139 |
+
profile = None
|
| 140 |
+
|
| 141 |
+
grounding = None
|
| 142 |
+
if profile == "BrainNavigator-v1":
|
| 143 |
+
try:
|
| 144 |
+
grounding = await asyncio.to_thread(
|
| 145 |
+
_o.agent_rag_context, prompt or "", k=6)
|
| 146 |
+
except Exception as exc:
|
| 147 |
+
grounding = {
|
| 148 |
+
"schema": "szl.brain.navigator-context/v1",
|
| 149 |
+
"state": "ABSTAIN_RETRIEVAL_ERROR",
|
| 150 |
+
"ready": False,
|
| 151 |
+
"content_access": "HANDLES_ONLY",
|
| 152 |
+
"handles": [],
|
| 153 |
+
"evidence": [],
|
| 154 |
+
"honesty": f"Brain retrieval raised {type(exc).__name__}; no grounding fabricated",
|
| 155 |
+
}
|
| 156 |
+
if not grounding.get("ready"):
|
| 157 |
+
attestation = None
|
| 158 |
+
try:
|
| 159 |
+
attestation = await asyncio.to_thread(
|
| 160 |
+
_o.attest_local_model, profile)
|
| 161 |
+
except Exception:
|
| 162 |
+
pass
|
| 163 |
+
return {
|
| 164 |
+
"text": None,
|
| 165 |
+
"model": ((attestation or {}).get("expected_model") or "khipu-unavailable"),
|
| 166 |
+
"stub": True,
|
| 167 |
+
"timeout": False,
|
| 168 |
+
"token_budget": bounded_tokens,
|
| 169 |
+
"timeout_s": bounded_timeout,
|
| 170 |
+
"honesty": (grounding.get("honesty") or
|
| 171 |
+
"no Brain evidence cleared the retrieval gate; abstaining"),
|
| 172 |
+
"grounding": grounding,
|
| 173 |
+
"model_attestation": attestation,
|
| 174 |
+
}
|
| 175 |
+
messages[1]["content"] = (
|
| 176 |
+
(prompt or "")
|
| 177 |
+
+ "\n\nCANDIDATE_HANDLES_JSON (controller-provided; no node content):\n"
|
| 178 |
+
+ json.dumps(grounding["handles"], sort_keys=True,
|
| 179 |
+
separators=(",", ":"), ensure_ascii=False)
|
| 180 |
+
+ "\nReturn a retrieval plan using only offered nodeId values. "
|
| 181 |
+
"If none supports the query, return ABSTAIN with zero citations."
|
| 182 |
+
)
|
| 183 |
+
grounding["augmented_prompt_sha256"] = hashlib.sha256(
|
| 184 |
+
messages[1]["content"].encode("utf-8")).hexdigest()
|
| 185 |
try:
|
| 186 |
result = await asyncio.wait_for(
|
| 187 |
_o.agent_model_complete(
|
| 188 |
+
messages, max_tokens=bounded_tokens, temperature=temperature,
|
| 189 |
+
local_profile=profile),
|
| 190 |
timeout=bounded_timeout,
|
| 191 |
)
|
| 192 |
except asyncio.TimeoutError:
|
|
|
|
| 225 |
"timeout_s": bounded_timeout,
|
| 226 |
"honesty": "model backend returned a non-contract value; no answer was used",
|
| 227 |
}
|
| 228 |
+
answer = result.get("text", "")
|
| 229 |
+
if profile == "BrainNavigator-v1" and grounding is not None:
|
| 230 |
+
citation_state = "NOT_DECLARED_UNSTRUCTURED_OUTPUT"
|
| 231 |
+
cited_node_ids: list[str] = []
|
| 232 |
+
citation_error = None
|
| 233 |
+
if isinstance(answer, str):
|
| 234 |
+
candidate = answer.strip()
|
| 235 |
+
if candidate.startswith("```") and candidate.endswith("```"):
|
| 236 |
+
candidate = candidate[3:-3].strip()
|
| 237 |
+
if candidate.lower().startswith("json"):
|
| 238 |
+
candidate = candidate[4:].lstrip()
|
| 239 |
+
try:
|
| 240 |
+
parsed_answer = json.loads(candidate)
|
| 241 |
+
except (TypeError, ValueError):
|
| 242 |
+
parsed_answer = None
|
| 243 |
+
if isinstance(parsed_answer, dict):
|
| 244 |
+
declared = (
|
| 245 |
+
parsed_answer.get("citedNodeIds")
|
| 246 |
+
if "citedNodeIds" in parsed_answer
|
| 247 |
+
else parsed_answer.get("cited_node_ids")
|
| 248 |
+
if "cited_node_ids" in parsed_answer
|
| 249 |
+
else None
|
| 250 |
+
)
|
| 251 |
+
if declared is not None:
|
| 252 |
+
if (not isinstance(declared, list)
|
| 253 |
+
or any(not isinstance(item, str) or not item
|
| 254 |
+
for item in declared)):
|
| 255 |
+
citation_state = "INVALID_CITATION_CONTRACT"
|
| 256 |
+
citation_error = "cited node IDs must be a list of non-empty strings"
|
| 257 |
+
else:
|
| 258 |
+
cited_node_ids = list(dict.fromkeys(declared))
|
| 259 |
+
offered = {
|
| 260 |
+
row.get("nodeId") for row in grounding.get("handles", [])
|
| 261 |
+
if isinstance(row, dict) and isinstance(row.get("nodeId"), str)
|
| 262 |
+
}
|
| 263 |
+
unknown = sorted(set(cited_node_ids) - offered)
|
| 264 |
+
if unknown:
|
| 265 |
+
citation_state = "UNKNOWN_CITATION_REFUSED"
|
| 266 |
+
citation_error = (
|
| 267 |
+
"model cited node IDs outside the controller-offered handle set"
|
| 268 |
+
)
|
| 269 |
+
else:
|
| 270 |
+
citation_state = "CITATIONS_WITHIN_OFFERED_HANDLES"
|
| 271 |
+
grounding["citation_validation"] = {
|
| 272 |
+
"state": citation_state,
|
| 273 |
+
"cited_node_ids": cited_node_ids,
|
| 274 |
+
"cited_node_ids_sha256": hashlib.sha256(json.dumps(
|
| 275 |
+
cited_node_ids, sort_keys=True, separators=(",", ":"),
|
| 276 |
+
ensure_ascii=False
|
| 277 |
+
).encode("utf-8")).hexdigest(),
|
| 278 |
+
}
|
| 279 |
+
if citation_error:
|
| 280 |
+
grounding["citation_validation"]["honesty"] = citation_error
|
| 281 |
+
rejected_output_sha256 = (
|
| 282 |
+
hashlib.sha256(answer.encode("utf-8")).hexdigest()
|
| 283 |
+
if isinstance(answer, str) else None
|
| 284 |
+
)
|
| 285 |
+
grounding["rejected_model_output_sha256"] = rejected_output_sha256
|
| 286 |
+
return {
|
| 287 |
+
"text": None,
|
| 288 |
+
"model": result.get("model"),
|
| 289 |
+
"stub": True,
|
| 290 |
+
"timeout": bool(result.get("timeout", False)),
|
| 291 |
+
"token_budget": bounded_tokens,
|
| 292 |
+
"timeout_s": bounded_timeout,
|
| 293 |
+
"honesty": citation_error + "; no ungrounded model text returned",
|
| 294 |
+
"raw_model_output_sha256": rejected_output_sha256,
|
| 295 |
+
"energy_receipt": result.get("energy_receipt"),
|
| 296 |
+
"model_attestation": result.get("model_attestation"),
|
| 297 |
+
"grounding": grounding,
|
| 298 |
+
}
|
| 299 |
return {
|
| 300 |
+
"text": answer,
|
| 301 |
"model": result.get("model"),
|
| 302 |
"stub": bool(result.get("stub")),
|
| 303 |
"timeout": bool(result.get("timeout", False)),
|
|
|
|
| 305 |
"timeout_s": bounded_timeout,
|
| 306 |
"honesty": result.get("honesty"),
|
| 307 |
"energy_receipt": result.get("energy_receipt"),
|
| 308 |
+
"model_attestation": result.get("model_attestation"),
|
| 309 |
+
"grounding": grounding,
|
| 310 |
}
|
|
@@ -65,7 +65,10 @@ async def run_turn(
|
|
| 65 |
"""
|
| 66 |
diff = persona.default_difficulty if difficulty is None else float(difficulty)
|
| 67 |
tier = select_tier(diff)
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
answer: Optional[str] = None
|
| 71 |
model: Optional[str] = None
|
|
@@ -74,6 +77,8 @@ async def run_turn(
|
|
| 74 |
token_budget: Optional[int] = None
|
| 75 |
timeout_s: Optional[float] = None
|
| 76 |
energy_receipt: Any = None
|
|
|
|
|
|
|
| 77 |
|
| 78 |
if model_complete is None:
|
| 79 |
honesty = ("model backend not injected — no answer fabricated. This turn "
|
|
@@ -108,16 +113,27 @@ async def run_turn(
|
|
| 108 |
token_budget = result.get("token_budget")
|
| 109 |
timeout_s = result.get("timeout_s")
|
| 110 |
energy_receipt = result.get("energy_receipt")
|
|
|
|
|
|
|
| 111 |
else:
|
| 112 |
answer = str(result)
|
| 113 |
honesty = "answer produced by a11oy's model backend" + (
|
| 114 |
-
" (clearly-labeled stub — no
|
|
|
|
| 115 |
if isinstance(result, dict) and result.get("honesty"):
|
| 116 |
honesty = str(result["honesty"])
|
| 117 |
except Exception as exc:
|
| 118 |
honesty = (f"model backend raised: {str(exc)[:120]} "
|
| 119 |
"(honest — no fabricated answer)")
|
| 120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
return {
|
| 122 |
"persona": persona.name,
|
| 123 |
"quechua": persona.quechua,
|
|
@@ -134,6 +150,10 @@ async def run_turn(
|
|
| 134 |
"token_budget": token_budget,
|
| 135 |
"timeout_s": timeout_s,
|
| 136 |
"energy_receipt": energy_receipt,
|
|
|
|
|
|
|
|
|
|
| 137 |
"honesty": honesty,
|
| 138 |
-
"evidence": []
|
|
|
|
| 139 |
}
|
|
|
|
| 65 |
"""
|
| 66 |
diff = persona.default_difficulty if difficulty is None else float(difficulty)
|
| 67 |
tier = select_tier(diff)
|
| 68 |
+
from .model_binding import persona_binding, prompt_contract
|
| 69 |
+
|
| 70 |
+
binding = persona_binding(persona.name)
|
| 71 |
+
system = persona.system_prompt() + "\n\n" + prompt_contract(binding)
|
| 72 |
|
| 73 |
answer: Optional[str] = None
|
| 74 |
model: Optional[str] = None
|
|
|
|
| 77 |
token_budget: Optional[int] = None
|
| 78 |
timeout_s: Optional[float] = None
|
| 79 |
energy_receipt: Any = None
|
| 80 |
+
model_attestation: Any = None
|
| 81 |
+
grounding: Any = None
|
| 82 |
|
| 83 |
if model_complete is None:
|
| 84 |
honesty = ("model backend not injected — no answer fabricated. This turn "
|
|
|
|
| 113 |
token_budget = result.get("token_budget")
|
| 114 |
timeout_s = result.get("timeout_s")
|
| 115 |
energy_receipt = result.get("energy_receipt")
|
| 116 |
+
model_attestation = result.get("model_attestation")
|
| 117 |
+
grounding = result.get("grounding")
|
| 118 |
else:
|
| 119 |
answer = str(result)
|
| 120 |
honesty = "answer produced by a11oy's model backend" + (
|
| 121 |
+
" (clearly-labeled stub — no reachable local or credentialed remote backend)"
|
| 122 |
+
if stub else "")
|
| 123 |
if isinstance(result, dict) and result.get("honesty"):
|
| 124 |
honesty = str(result["honesty"])
|
| 125 |
except Exception as exc:
|
| 126 |
honesty = (f"model backend raised: {str(exc)[:120]} "
|
| 127 |
"(honest — no fabricated answer)")
|
| 128 |
|
| 129 |
+
binding = persona_binding(
|
| 130 |
+
persona.name,
|
| 131 |
+
actual_model=model,
|
| 132 |
+
backend_mode=("stub" if stub else "live" if model else "unavailable"),
|
| 133 |
+
model_attestation=model_attestation,
|
| 134 |
+
grounding=grounding,
|
| 135 |
+
)
|
| 136 |
+
|
| 137 |
return {
|
| 138 |
"persona": persona.name,
|
| 139 |
"quechua": persona.quechua,
|
|
|
|
| 150 |
"token_budget": token_budget,
|
| 151 |
"timeout_s": timeout_s,
|
| 152 |
"energy_receipt": energy_receipt,
|
| 153 |
+
"model_attestation": model_attestation,
|
| 154 |
+
"grounding": grounding,
|
| 155 |
+
"model_binding": binding,
|
| 156 |
"honesty": honesty,
|
| 157 |
+
"evidence": (grounding.get("evidence", [])
|
| 158 |
+
if isinstance(grounding, dict) else []),
|
| 159 |
}
|
|
@@ -1,10 +1,11 @@
|
|
| 1 |
"""ayllu.lounge — the collaboration surface, learned from the tribe lounge/bus.
|
| 2 |
|
| 3 |
The tribe let souls talk in a shared room. a11oy keeps that, in-memory and honest: each
|
| 4 |
-
posted message carries a source label ("
|
| 5 |
-
"persona-fallback"), so a reader
|
| 6 |
-
|
| 7 |
-
per persona — and never fabricates when no backend is injected.
|
|
|
|
| 8 |
"""
|
| 9 |
from __future__ import annotations
|
| 10 |
|
|
@@ -37,6 +38,7 @@ class Lounge:
|
|
| 37 |
difficulty: float = 0.6,
|
| 38 |
two_person_attested: bool = False,
|
| 39 |
debate: bool = False,
|
|
|
|
| 40 |
) -> dict[str, Any]:
|
| 41 |
from .loop import run_turn
|
| 42 |
|
|
@@ -53,8 +55,10 @@ class Lounge:
|
|
| 53 |
)))
|
| 54 |
for p, turn in zip(personas, rounds):
|
| 55 |
turn["round"] = 1
|
| 56 |
-
src = "
|
| 57 |
-
|
|
|
|
|
|
|
| 58 |
|
| 59 |
mode = "single-round"
|
| 60 |
# Debate-then-converge (after arXiv:2305.14325, Multiagent Debate): one
|
|
@@ -88,10 +92,11 @@ class Lounge:
|
|
| 88 |
)))
|
| 89 |
for (p, _turn_prompt), turn in zip(debate_jobs, revised):
|
| 90 |
turn["round"] = 2
|
| 91 |
-
src = ("
|
| 92 |
-
else "persona-fallback")
|
| 93 |
-
|
| 94 |
-
|
|
|
|
| 95 |
rounds.append(turn)
|
| 96 |
else:
|
| 97 |
mode = "single-round"
|
|
@@ -101,6 +106,7 @@ class Lounge:
|
|
| 101 |
"participants": [p.name for p in personas],
|
| 102 |
"rounds": rounds,
|
| 103 |
"mode": mode,
|
|
|
|
| 104 |
"note": "bounded council; each turn honest (no fabrication when a model "
|
| 105 |
"backend is absent); debate mode = exactly two rounds, "
|
| 106 |
"after arXiv:2305.14325",
|
|
|
|
| 1 |
"""ayllu.lounge — the collaboration surface, learned from the tribe lounge/bus.
|
| 2 |
|
| 3 |
The tribe let souls talk in a shared room. a11oy keeps that, in-memory and honest: each
|
| 4 |
+
posted message carries a source label ("model-unverified" when a model answered,
|
| 5 |
+
else "persona-fallback"), so a reader never mistakes direct model text for grounded
|
| 6 |
+
Brain retrieval. `deliberate()` runs a BOUNDED council round — one honest turn
|
| 7 |
+
per persona — and never fabricates when no backend is injected. Publishing is
|
| 8 |
+
explicit opt-in; public ask/council calls keep their output out of this feed.
|
| 9 |
"""
|
| 10 |
from __future__ import annotations
|
| 11 |
|
|
|
|
| 38 |
difficulty: float = 0.6,
|
| 39 |
two_person_attested: bool = False,
|
| 40 |
debate: bool = False,
|
| 41 |
+
publish_to_lounge: bool = False,
|
| 42 |
) -> dict[str, Any]:
|
| 43 |
from .loop import run_turn
|
| 44 |
|
|
|
|
| 55 |
)))
|
| 56 |
for p, turn in zip(personas, rounds):
|
| 57 |
turn["round"] = 1
|
| 58 |
+
src = ("model-unverified" if turn.get("answer") is not None
|
| 59 |
+
and not turn.get("stub") else "persona-fallback")
|
| 60 |
+
if publish_to_lounge:
|
| 61 |
+
self.post(p.name, turn.get("answer") or turn.get("honesty"), source=src)
|
| 62 |
|
| 63 |
mode = "single-round"
|
| 64 |
# Debate-then-converge (after arXiv:2305.14325, Multiagent Debate): one
|
|
|
|
| 92 |
)))
|
| 93 |
for (p, _turn_prompt), turn in zip(debate_jobs, revised):
|
| 94 |
turn["round"] = 2
|
| 95 |
+
src = ("model-unverified" if turn.get("answer") is not None
|
| 96 |
+
and not turn.get("stub") else "persona-fallback")
|
| 97 |
+
if publish_to_lounge:
|
| 98 |
+
self.post(p.name, turn.get("answer") or turn.get("honesty"),
|
| 99 |
+
source=src)
|
| 100 |
rounds.append(turn)
|
| 101 |
else:
|
| 102 |
mode = "single-round"
|
|
|
|
| 106 |
"participants": [p.name for p in personas],
|
| 107 |
"rounds": rounds,
|
| 108 |
"mode": mode,
|
| 109 |
+
"published_to_lounge": publish_to_lounge,
|
| 110 |
"note": "bounded council; each turn honest (no fabrication when a model "
|
| 111 |
"backend is absent); debate mode = exactly two rounds, "
|
| 112 |
"after arXiv:2305.14325",
|
|
@@ -0,0 +1,402 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Honest runtime binding between the Ayllu council and SZL-Forge.
|
| 3 |
+
|
| 4 |
+
Ayllu personas are task roles sharing A11oy's routed model backend. They are
|
| 5 |
+
not eleven separately trained models. This module binds each role to a
|
| 6 |
+
declared SZL-Forge profile and a bounded set of *proposal* capabilities while
|
| 7 |
+
leaving execution, approval, signing, and verification in independent runtime
|
| 8 |
+
organs.
|
| 9 |
+
"""
|
| 10 |
+
from __future__ import annotations
|
| 11 |
+
|
| 12 |
+
import copy
|
| 13 |
+
import json
|
| 14 |
+
from typing import Any, Mapping
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
SCHEMA = "szl.ayllu.model-family-binding/v1"
|
| 18 |
+
SECOND_BRAIN_SCHEMA = "szl.khipu.compound-second-brain.v1"
|
| 19 |
+
FAMILY_ID = "SZL-Forge-1.5B"
|
| 20 |
+
COMPUTE_PLANE = "SZL-Yupaq"
|
| 21 |
+
BINDING_STATE = "PROFILE_AWARE_LOCAL_ROUTING_ARTIFACT_BINDING_PARTIAL"
|
| 22 |
+
|
| 23 |
+
_ALL_COMPUTE_OPERATIONS = (
|
| 24 |
+
"formula.org_lambda.weighted_geomean",
|
| 25 |
+
"quant.sample.pipeline",
|
| 26 |
+
"quantum.qubo.exact_baseline",
|
| 27 |
+
"numerics.external.run",
|
| 28 |
+
"numerics.external.compare",
|
| 29 |
+
"proof.lean.inventory",
|
| 30 |
+
"formula.admission.inventory",
|
| 31 |
+
"brain.corpus.inventory",
|
| 32 |
+
"lake.evidence.inventory",
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
_PROFILE_STATES = {
|
| 36 |
+
"ReceiptAgent-v1": "SIGNED_RECEIPTS_VALID_ARTIFACT_BINDING_CONFLICT",
|
| 37 |
+
"BrainNavigator-v1": "SIGNED_RECEIPTS_VALID_ARTIFACT_BINDING_CONFLICT",
|
| 38 |
+
"Operator-v1": "PLANNED_TOOL_CONTRACT_REQUIRED",
|
| 39 |
+
"Sentinel-v1": "PLANNED_SECURITY_ADMISSION_REQUIRED",
|
| 40 |
+
"Anatomy-v1": "PLANNED_ONTOLOGY_ADMISSION_REQUIRED",
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
_PERSONA_BINDINGS: dict[str, dict[str, Any]] = {
|
| 44 |
+
"Amaru": {
|
| 45 |
+
"primary_profile": "Operator-v1",
|
| 46 |
+
"supporting_profiles": ["Anatomy-v1"],
|
| 47 |
+
"proposal_surfaces": ["architecture.review", "anatomy.inspect"],
|
| 48 |
+
"compute_operations": [],
|
| 49 |
+
},
|
| 50 |
+
"Ruwaq": {
|
| 51 |
+
"primary_profile": "Operator-v1",
|
| 52 |
+
"supporting_profiles": [],
|
| 53 |
+
"proposal_surfaces": ["code.plan", "build.review", "compute.submit"],
|
| 54 |
+
"compute_operations": [
|
| 55 |
+
"proof.lean.inventory",
|
| 56 |
+
"formula.admission.inventory",
|
| 57 |
+
"brain.corpus.inventory",
|
| 58 |
+
"lake.evidence.inventory",
|
| 59 |
+
],
|
| 60 |
+
},
|
| 61 |
+
"Yupaq": {
|
| 62 |
+
"primary_profile": "ReceiptAgent-v1",
|
| 63 |
+
"supporting_profiles": ["BrainNavigator-v1"],
|
| 64 |
+
"proposal_surfaces": ["compute.submit", "receipt.verify", "proof.review"],
|
| 65 |
+
"compute_operations": list(_ALL_COMPUTE_OPERATIONS),
|
| 66 |
+
},
|
| 67 |
+
"Qhaway": {
|
| 68 |
+
"primary_profile": "Sentinel-v1",
|
| 69 |
+
"supporting_profiles": ["Anatomy-v1"],
|
| 70 |
+
"proposal_surfaces": ["simulation.review", "failure.evaluate"],
|
| 71 |
+
"compute_operations": ["quantum.qubo.exact_baseline"],
|
| 72 |
+
},
|
| 73 |
+
"Maskaq": {
|
| 74 |
+
"primary_profile": "BrainNavigator-v1",
|
| 75 |
+
"supporting_profiles": ["ReceiptAgent-v1"],
|
| 76 |
+
"proposal_surfaces": ["brain.query", "evidence.retrieve", "citation.review"],
|
| 77 |
+
"compute_operations": [
|
| 78 |
+
"brain.corpus.inventory",
|
| 79 |
+
"formula.admission.inventory",
|
| 80 |
+
"lake.evidence.inventory",
|
| 81 |
+
],
|
| 82 |
+
},
|
| 83 |
+
"Hampiq": {
|
| 84 |
+
"primary_profile": "Anatomy-v1",
|
| 85 |
+
"supporting_profiles": ["Sentinel-v1"],
|
| 86 |
+
"proposal_surfaces": ["health.inspect", "remediation.propose"],
|
| 87 |
+
"compute_operations": ["lake.evidence.inventory"],
|
| 88 |
+
},
|
| 89 |
+
"Yanapaq": {
|
| 90 |
+
"primary_profile": "Operator-v1",
|
| 91 |
+
"supporting_profiles": [],
|
| 92 |
+
"proposal_surfaces": ["ops.review", "incident.support"],
|
| 93 |
+
"compute_operations": [],
|
| 94 |
+
},
|
| 95 |
+
"Chaka": {
|
| 96 |
+
"primary_profile": "Operator-v1",
|
| 97 |
+
"supporting_profiles": ["ReceiptAgent-v1"],
|
| 98 |
+
"proposal_surfaces": ["connector.review", "contract.crosswalk"],
|
| 99 |
+
"compute_operations": [],
|
| 100 |
+
},
|
| 101 |
+
"Kamachiq": {
|
| 102 |
+
"primary_profile": "Operator-v1",
|
| 103 |
+
"supporting_profiles": ["ReceiptAgent-v1"],
|
| 104 |
+
"proposal_surfaces": ["route.review", "plan.sequence", "approval.request"],
|
| 105 |
+
"compute_operations": [],
|
| 106 |
+
},
|
| 107 |
+
"Qhatuq": {
|
| 108 |
+
"primary_profile": "ReceiptAgent-v1",
|
| 109 |
+
"supporting_profiles": [],
|
| 110 |
+
"proposal_surfaces": ["risk.review", "quant.compute"],
|
| 111 |
+
"compute_operations": [
|
| 112 |
+
"quant.sample.pipeline",
|
| 113 |
+
"formula.org_lambda.weighted_geomean",
|
| 114 |
+
],
|
| 115 |
+
},
|
| 116 |
+
"Willakuq": {
|
| 117 |
+
"primary_profile": "ReceiptAgent-v1",
|
| 118 |
+
"supporting_profiles": [],
|
| 119 |
+
"proposal_surfaces": ["receipt.verify", "provenance.review", "archive.propose"],
|
| 120 |
+
"compute_operations": ["lake.evidence.inventory"],
|
| 121 |
+
},
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
_HARD_BOUNDARIES = {
|
| 125 |
+
"personas_are_separate_weights": False,
|
| 126 |
+
"tool_dispatch_active": False,
|
| 127 |
+
"can_execute_external_actions": False,
|
| 128 |
+
"can_approve_own_proposal": False,
|
| 129 |
+
"can_sign_own_evidence": False,
|
| 130 |
+
"can_self_certify_correctness": False,
|
| 131 |
+
"model_output_is_verified_truth": False,
|
| 132 |
+
"automatic_lounge_publish": False,
|
| 133 |
+
"compute_execution_location": "SZL-Yupaq external governed computation plane",
|
| 134 |
+
"binding_rule": "MODEL_PROPOSES; YUPAQ_VALIDATES_SCHEMA; ENGINE_COMPUTES; HONESTY_LABELS; RECEIPT_BINDS",
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def persona_binding(
|
| 139 |
+
name: str,
|
| 140 |
+
*,
|
| 141 |
+
actual_model: Any = None,
|
| 142 |
+
backend_mode: str | None = None,
|
| 143 |
+
model_attestation: Mapping[str, Any] | None = None,
|
| 144 |
+
grounding: Mapping[str, Any] | None = None,
|
| 145 |
+
) -> dict[str, Any]:
|
| 146 |
+
"""Return one role's immutable model/control-plane binding."""
|
| 147 |
+
canonical = next((key for key in _PERSONA_BINDINGS if key.lower() == (name or "").lower()), None)
|
| 148 |
+
if canonical is None:
|
| 149 |
+
raise KeyError(f"unknown Ayllu persona: {name}")
|
| 150 |
+
binding = copy.deepcopy(_PERSONA_BINDINGS[canonical])
|
| 151 |
+
primary = binding["primary_profile"]
|
| 152 |
+
attestation = copy.deepcopy(dict(model_attestation or {})) or None
|
| 153 |
+
grounding_summary = None
|
| 154 |
+
if grounding:
|
| 155 |
+
grounding_summary = {
|
| 156 |
+
"schema": grounding.get("schema"),
|
| 157 |
+
"state": grounding.get("state"),
|
| 158 |
+
"content_access": grounding.get("content_access"),
|
| 159 |
+
"query_sha256": grounding.get("query_sha256"),
|
| 160 |
+
"evidence_set_sha256": grounding.get("evidence_set_sha256"),
|
| 161 |
+
"handles_sha256": grounding.get("handles_sha256"),
|
| 162 |
+
"augmented_prompt_sha256": grounding.get("augmented_prompt_sha256"),
|
| 163 |
+
"handle_evidence_set_equivalent": grounding.get(
|
| 164 |
+
"handle_evidence_set_equivalent"),
|
| 165 |
+
"citation_validation": copy.deepcopy(
|
| 166 |
+
grounding.get("citation_validation")),
|
| 167 |
+
"rejected_model_output_sha256": grounding.get(
|
| 168 |
+
"rejected_model_output_sha256"),
|
| 169 |
+
"grounded_count": grounding.get("grounded_count"),
|
| 170 |
+
}
|
| 171 |
+
attested_served_model = (
|
| 172 |
+
attestation.get("served_model") if attestation is not None else None)
|
| 173 |
+
model_identity_reconciled = (
|
| 174 |
+
actual_model == attested_served_model
|
| 175 |
+
if isinstance(attested_served_model, str) and attested_served_model
|
| 176 |
+
else None
|
| 177 |
+
)
|
| 178 |
+
binding.update({
|
| 179 |
+
"schema": SCHEMA,
|
| 180 |
+
"persona": canonical,
|
| 181 |
+
"family_id": FAMILY_ID,
|
| 182 |
+
"binding_state": BINDING_STATE,
|
| 183 |
+
"profile_state": _PROFILE_STATES[primary],
|
| 184 |
+
"actual_model": actual_model,
|
| 185 |
+
"backend_mode": backend_mode or "NOT_OBSERVED",
|
| 186 |
+
"actual_model_authority": "turn receipt and router evidence",
|
| 187 |
+
"attested_served_model": attested_served_model,
|
| 188 |
+
"model_identity_reconciled": model_identity_reconciled,
|
| 189 |
+
"model_attestation": attestation,
|
| 190 |
+
"model_attestation_sha256": (
|
| 191 |
+
_canonical_sha256(attestation) if attestation is not None else None
|
| 192 |
+
),
|
| 193 |
+
"grounding": grounding_summary,
|
| 194 |
+
"grounding_sha256": (
|
| 195 |
+
_canonical_sha256(grounding_summary) if grounding_summary is not None else None
|
| 196 |
+
),
|
| 197 |
+
"compute_plane": COMPUTE_PLANE,
|
| 198 |
+
"authority": "PROPOSAL_ONLY",
|
| 199 |
+
"hard_boundaries": copy.deepcopy(_HARD_BOUNDARIES),
|
| 200 |
+
})
|
| 201 |
+
return binding
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def family_binding(
|
| 205 |
+
*,
|
| 206 |
+
namespace: str = "a11oy",
|
| 207 |
+
backend_status: Mapping[str, Any] | None = None,
|
| 208 |
+
) -> dict[str, Any]:
|
| 209 |
+
"""Return the machine-readable Ayllu-to-Forge family contract."""
|
| 210 |
+
status = dict(backend_status or {})
|
| 211 |
+
profile_runtime = status.get("forge_profiles")
|
| 212 |
+
return {
|
| 213 |
+
"schema": SCHEMA,
|
| 214 |
+
"family_id": FAMILY_ID,
|
| 215 |
+
"binding_state": BINDING_STATE,
|
| 216 |
+
"runtime_backend": status,
|
| 217 |
+
"runtime_backend_is_profile_pinned": False,
|
| 218 |
+
"runtime_profile_status": profile_runtime,
|
| 219 |
+
"profile_pin_requirement": (
|
| 220 |
+
"The exact profile tag must be observed, its immutable weight/blob digest must "
|
| 221 |
+
"match a signed release manifest, and the turn receipt must bind that attestation."
|
| 222 |
+
),
|
| 223 |
+
"personas": [persona_binding(name) for name in _PERSONA_BINDINGS],
|
| 224 |
+
"compute": {
|
| 225 |
+
"plane_id": COMPUTE_PLANE,
|
| 226 |
+
"capabilities_endpoint": f"/api/{namespace}/v1/compute/capabilities",
|
| 227 |
+
"submit_endpoint": f"/api/{namespace}/v1/compute/jobs",
|
| 228 |
+
"allowed_operations": list(_ALL_COMPUTE_OPERATIONS),
|
| 229 |
+
"dispatch_state": "PROPOSAL_ONLY_NOT_ACTIVE_IN_AYLLU_LOOP",
|
| 230 |
+
"stateful_routes_require_auth": True,
|
| 231 |
+
},
|
| 232 |
+
"hard_boundaries": copy.deepcopy(_HARD_BOUNDARIES),
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def second_brain_binding(
|
| 237 |
+
*,
|
| 238 |
+
namespace: str = "a11oy",
|
| 239 |
+
backend_status: Mapping[str, Any] | None = None,
|
| 240 |
+
rag_status: Mapping[str, Any] | None = None,
|
| 241 |
+
signer_ready: bool = False,
|
| 242 |
+
) -> dict[str, Any]:
|
| 243 |
+
"""Describe the Khipu Second Brain as an evidence-bound compound model.
|
| 244 |
+
|
| 245 |
+
The generator tag, persistent retrieval index, controller, and receipt
|
| 246 |
+
verifier are independent components. Keeping that separation explicit
|
| 247 |
+
prevents an index row count from being mislabeled as parameters or trained
|
| 248 |
+
weights while still exposing one operational system contract.
|
| 249 |
+
"""
|
| 250 |
+
backend = copy.deepcopy(dict(backend_status or {}))
|
| 251 |
+
rag = copy.deepcopy(dict(rag_status or {}))
|
| 252 |
+
profile_runtime = (
|
| 253 |
+
(backend.get("forge_profiles") or {}).get("profiles") or {}
|
| 254 |
+
).get("BrainNavigator-v1") or {}
|
| 255 |
+
exact_tag_observed = bool(profile_runtime.get("available"))
|
| 256 |
+
index_ready = bool(rag.get("built"))
|
| 257 |
+
ready = exact_tag_observed and index_ready
|
| 258 |
+
if ready:
|
| 259 |
+
state = "READY_FOR_GROUNDED_NAVIGATION_ARTIFACT_UNBOUND"
|
| 260 |
+
elif not exact_tag_observed and not index_ready:
|
| 261 |
+
state = "UNAVAILABLE_MODEL_AND_INDEX"
|
| 262 |
+
elif not exact_tag_observed:
|
| 263 |
+
state = "UNAVAILABLE_MODEL_TAG_MISSING"
|
| 264 |
+
else:
|
| 265 |
+
state = "UNAVAILABLE_INDEX_NOT_BUILT"
|
| 266 |
+
return {
|
| 267 |
+
"schema": SECOND_BRAIN_SCHEMA,
|
| 268 |
+
"system_id": "SZL-Khipu-Second-Brain-v1",
|
| 269 |
+
"system_type": "COMPOUND_MODEL_WITH_EXTERNAL_EVIDENCE_MEMORY",
|
| 270 |
+
"state": state,
|
| 271 |
+
"ready_for_grounded_navigation": ready,
|
| 272 |
+
"live_grounded_turn_verified_this_request": False,
|
| 273 |
+
"signer_ready_this_request": bool(signer_ready),
|
| 274 |
+
"promotion_state": "BLOCKED_ARTIFACT_AND_EVAL_GATES",
|
| 275 |
+
"profile": {
|
| 276 |
+
"profile_id": "BrainNavigator-v1",
|
| 277 |
+
"expected_model": profile_runtime.get("expected_model", "khipu:latest"),
|
| 278 |
+
"served_model": profile_runtime.get("served_model"),
|
| 279 |
+
"exact_tag_observed": exact_tag_observed,
|
| 280 |
+
"artifact_binding": "UNBOUND",
|
| 281 |
+
"turn_level_attestation_required": True,
|
| 282 |
+
},
|
| 283 |
+
"memory": {
|
| 284 |
+
"kind": "PERSISTENT_SQLITE_HYBRID_RETRIEVAL_GRAPH",
|
| 285 |
+
"built": index_ready,
|
| 286 |
+
"document_count": rag.get("document_count", rag.get("files")),
|
| 287 |
+
"chunk_count": rag.get("chunk_count", rag.get("chunks")),
|
| 288 |
+
"corpus_chunk_count": rag.get(
|
| 289 |
+
"corpus_chunk_count", rag.get("chunk_count", rag.get("chunks"))
|
| 290 |
+
),
|
| 291 |
+
"brain_handle_count": rag.get("brain_handle_count", 0),
|
| 292 |
+
"brain_handle_plane": rag.get("brain_handle_plane"),
|
| 293 |
+
"training_authority_rows": rag.get("training_authority_rows", 0),
|
| 294 |
+
"node_count": rag.get("node_count"),
|
| 295 |
+
"edge_count": rag.get("edge_count"),
|
| 296 |
+
"generation_id": rag.get("generation_id"),
|
| 297 |
+
"generation_digest_sha256": rag.get("generation_digest_sha256"),
|
| 298 |
+
"integrity_state": rag.get("integrity_state"),
|
| 299 |
+
"rehydration_state": rag.get("rehydration_state"),
|
| 300 |
+
"corpus": rag.get("corpus"),
|
| 301 |
+
"index_mode": rag.get("mode"),
|
| 302 |
+
"scope_boundary": (
|
| 303 |
+
"Corpus chunks and the canonical 9,464-node Brain handle plane are "
|
| 304 |
+
"separate, independently counted retrieval planes. Handles preserve "
|
| 305 |
+
"source and quarantine metadata and grant no gradient authority."
|
| 306 |
+
),
|
| 307 |
+
"evidence_access": "HANDLES_ONLY_TO_MODEL; CONTENT_STAYS_IN_CONTROLLER",
|
| 308 |
+
},
|
| 309 |
+
"grounding": {
|
| 310 |
+
"ask_endpoint": f"/api/{namespace}/v1/ayllu/ask",
|
| 311 |
+
"persona": "Maskaq",
|
| 312 |
+
"query_endpoint": f"/api/{namespace}/code/rag/query",
|
| 313 |
+
"required_receipt_fields": [
|
| 314 |
+
"evidence_set_sha256",
|
| 315 |
+
"handles_sha256",
|
| 316 |
+
"augmented_prompt_sha256",
|
| 317 |
+
"grounding_sha256",
|
| 318 |
+
"model_attestation_sha256",
|
| 319 |
+
"turn_output_sha256",
|
| 320 |
+
],
|
| 321 |
+
"abstain_when_ungrounded": True,
|
| 322 |
+
},
|
| 323 |
+
"training_boundary": {
|
| 324 |
+
"raw_brain_nodes_observed": 9464,
|
| 325 |
+
"raw_brain_nodes_admitted_to_gradients": 0,
|
| 326 |
+
"admission_is_row_level": True,
|
| 327 |
+
"admission_engine": "szl_brain_training_admission.py",
|
| 328 |
+
"admission_contract": "szl.brain-training-admission-report.v1",
|
| 329 |
+
"evidence_security": "ED25519_ALLOWLISTED_ISSUER_TOOL_KEY",
|
| 330 |
+
"required_signed_inputs": [
|
| 331 |
+
"protected_eval_content_sha256_list",
|
| 332 |
+
"signed_evidence_trust_store",
|
| 333 |
+
"signed_prior_split_ledger_descriptor",
|
| 334 |
+
],
|
| 335 |
+
"current_state": (
|
| 336 |
+
"ROW_LEVEL_ADMISSION_ENGINE_IMPLEMENTED_CURRENT_RAW_ROWS_QUARANTINED"
|
| 337 |
+
),
|
| 338 |
+
"required": [
|
| 339 |
+
"stable_node_id",
|
| 340 |
+
"content_sha256",
|
| 341 |
+
"immutable_source_revision",
|
| 342 |
+
"rights_basis_and_license",
|
| 343 |
+
"source_timestamp_and_freshness",
|
| 344 |
+
"canonical_state",
|
| 345 |
+
"dedup_group",
|
| 346 |
+
"contamination_result",
|
| 347 |
+
"immutable_split",
|
| 348 |
+
"cross_run_split_ledger_binding",
|
| 349 |
+
],
|
| 350 |
+
"honesty": (
|
| 351 |
+
"All graph nodes may participate in retrieval and evaluation; only "
|
| 352 |
+
"independently admitted rows may enter gradients."
|
| 353 |
+
),
|
| 354 |
+
},
|
| 355 |
+
"hard_boundaries": {
|
| 356 |
+
"index_is_model_weights": False,
|
| 357 |
+
"retrieval_is_training": False,
|
| 358 |
+
"model_can_read_raw_node_content": False,
|
| 359 |
+
"model_can_write_canonical_memory": False,
|
| 360 |
+
"model_can_self_certify_grounding": False,
|
| 361 |
+
},
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
|
| 365 |
+
def prompt_contract(binding: Mapping[str, Any]) -> str:
|
| 366 |
+
"""Serialize the binding into a compact system-prompt control contract."""
|
| 367 |
+
compact = {
|
| 368 |
+
"schema": binding.get("schema"),
|
| 369 |
+
"family_id": binding.get("family_id"),
|
| 370 |
+
"persona": binding.get("persona"),
|
| 371 |
+
"primary_profile": binding.get("primary_profile"),
|
| 372 |
+
"profile_state": binding.get("profile_state"),
|
| 373 |
+
"authority": binding.get("authority"),
|
| 374 |
+
"proposal_surfaces": binding.get("proposal_surfaces"),
|
| 375 |
+
"compute_operations": binding.get("compute_operations"),
|
| 376 |
+
"binding_rule": (binding.get("hard_boundaries") or {}).get("binding_rule"),
|
| 377 |
+
}
|
| 378 |
+
return (
|
| 379 |
+
"A11OY MODEL-BINDING CONTRACT (machine-readable; binding):\n"
|
| 380 |
+
+ json.dumps(compact, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
| 381 |
+
+ "\nYou may propose only. Never claim that a proposal was executed, approved, "
|
| 382 |
+
"signed, kernel-verified, or trained unless an independent receipt is present."
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
def _canonical_sha256(value: Any) -> str:
|
| 387 |
+
return __import__("hashlib").sha256(json.dumps(
|
| 388 |
+
value, sort_keys=True, separators=(",", ":"), ensure_ascii=False
|
| 389 |
+
).encode("utf-8")).hexdigest()
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
__all__ = [
|
| 393 |
+
"BINDING_STATE",
|
| 394 |
+
"COMPUTE_PLANE",
|
| 395 |
+
"FAMILY_ID",
|
| 396 |
+
"SCHEMA",
|
| 397 |
+
"SECOND_BRAIN_SCHEMA",
|
| 398 |
+
"family_binding",
|
| 399 |
+
"persona_binding",
|
| 400 |
+
"prompt_contract",
|
| 401 |
+
"second_brain_binding",
|
| 402 |
+
]
|
|
@@ -48,7 +48,8 @@ def main() -> None:
|
|
| 48 |
# Lounge deliberation, honest (no backend => no fabricated answers).
|
| 49 |
lounge = Lounge()
|
| 50 |
res = asyncio.run(lounge.deliberate(
|
| 51 |
-
"What are the risks?", [get_persona("qhatuq"), get_persona("qhaway")]
|
|
|
|
| 52 |
assert len(res["rounds"]) == 2
|
| 53 |
assert all(r["answer"] is None for r in res["rounds"])
|
| 54 |
assert len(lounge.recent()) == 2
|
|
@@ -64,8 +65,8 @@ def main() -> None:
|
|
| 64 |
assert wired["stub"] is True and wired["answer"] and \
|
| 65 |
"honest" in wired["answer"].lower(), wired
|
| 66 |
|
| 67 |
-
print(f"AYLLU SELFTEST OK
|
| 68 |
-
f"honest fallbacks;
|
| 69 |
f"{st['mode']}.")
|
| 70 |
|
| 71 |
|
|
|
|
| 48 |
# Lounge deliberation, honest (no backend => no fabricated answers).
|
| 49 |
lounge = Lounge()
|
| 50 |
res = asyncio.run(lounge.deliberate(
|
| 51 |
+
"What are the risks?", [get_persona("qhatuq"), get_persona("qhaway")],
|
| 52 |
+
publish_to_lounge=True))
|
| 53 |
assert len(res["rounds"]) == 2
|
| 54 |
assert all(r["answer"] is None for r in res["rounds"])
|
| 55 |
assert len(lounge.recent()) == 2
|
|
|
|
| 65 |
assert wired["stub"] is True and wired["answer"] and \
|
| 66 |
"honest" in wired["answer"].lower(), wired
|
| 67 |
|
| 68 |
+
print(f"AYLLU SELFTEST OK - {len(ROSTER)} personas; tier router + bounded loop "
|
| 69 |
+
f"honest fallbacks; Lambda-gate fail-closed; lounge honest; backend mode="
|
| 70 |
f"{st['mode']}.")
|
| 71 |
|
| 72 |
|
|
@@ -0,0 +1,511 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Deterministic draft-to-envelope bridge for SZL-Forge ReceiptAgent.
|
| 2 |
+
|
| 3 |
+
The model emits ``szl.forge-receipt-draft.v1``. This module never trusts the
|
| 4 |
+
model to admit evidence, determine formula proof status, authorize a tool, or
|
| 5 |
+
sign a receipt. It resolves those facts from caller-supplied immutable
|
| 6 |
+
snapshots and only returns an ANSWERED final envelope when an external receipt
|
| 7 |
+
has already been verified against the exact computed bindings.
|
| 8 |
+
|
| 9 |
+
This module performs no network calls, tool execution, signing, or secret
|
| 10 |
+
access. Those remain deployment boundaries of the A11oy runtime.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
from __future__ import annotations
|
| 14 |
+
|
| 15 |
+
import base64
|
| 16 |
+
import hashlib
|
| 17 |
+
import hmac
|
| 18 |
+
import json
|
| 19 |
+
import re
|
| 20 |
+
import threading
|
| 21 |
+
from copy import deepcopy
|
| 22 |
+
from typing import Any, Mapping
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
DRAFT_SCHEMA_VERSION = "szl.forge-receipt-draft.v1"
|
| 26 |
+
FINAL_SCHEMA_VERSION = "szl.receipt-agent-output.v1"
|
| 27 |
+
CANONICAL_CANDIDATE_ID = "SZL-Forge-1.5B-ReceiptAgent-v1"
|
| 28 |
+
RECEIPT_PAYLOAD_TYPE = "application/vnd.szl.receipt-agent-binding+json"
|
| 29 |
+
SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
|
| 30 |
+
EVIDENCE_ID_RE = re.compile(r"^(fixture|brain|artifact|source|receipt):[A-Za-z0-9._:/-]+$")
|
| 31 |
+
FINAL_EVIDENCE_ID_RE = re.compile(r"^(brain|artifact|source|receipt):[A-Za-z0-9._:/-]+$")
|
| 32 |
+
FORMULA_STATUS = {"KERNEL_ACCEPTED", "CONDITIONAL", "OPEN", "REFUTED", "NOT_EVALUATED"}
|
| 33 |
+
ABSTENTION_CODES = {
|
| 34 |
+
"NONE",
|
| 35 |
+
"MODEL_UNAVAILABLE",
|
| 36 |
+
"EVIDENCE_NOT_ADMITTED",
|
| 37 |
+
"EVIDENCE_INSUFFICIENT",
|
| 38 |
+
"FORMULA_NAMESPACE_CONFLICT",
|
| 39 |
+
"RECEIPT_INVALID",
|
| 40 |
+
"POLICY_DENIED",
|
| 41 |
+
"UNCERTAINTY_TOO_HIGH",
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class ReceiptRuntimeError(ValueError):
|
| 46 |
+
"""Raised when an input violates the deterministic runtime contract."""
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class ReceiptReplayGuard:
|
| 50 |
+
"""Process-local single-use guard; deployments must back this with durable storage."""
|
| 51 |
+
|
| 52 |
+
def __init__(self) -> None:
|
| 53 |
+
self._lock = threading.Lock()
|
| 54 |
+
self._consumed: set[str] = set()
|
| 55 |
+
|
| 56 |
+
def consume(self, receipt_id: str) -> bool:
|
| 57 |
+
with self._lock:
|
| 58 |
+
if receipt_id in self._consumed:
|
| 59 |
+
return False
|
| 60 |
+
self._consumed.add(receipt_id)
|
| 61 |
+
return True
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def canonical_bytes(value: Any) -> bytes:
|
| 65 |
+
return json.dumps(
|
| 66 |
+
value,
|
| 67 |
+
sort_keys=True,
|
| 68 |
+
separators=(",", ":"),
|
| 69 |
+
ensure_ascii=False,
|
| 70 |
+
allow_nan=False,
|
| 71 |
+
).encode("utf-8")
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def canonical_sha256(value: Any) -> str:
|
| 75 |
+
return hashlib.sha256(canonical_bytes(value)).hexdigest()
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def _dsse_pae(payload_type: str, payload: bytes) -> bytes:
|
| 79 |
+
payload_type_bytes = payload_type.encode("utf-8")
|
| 80 |
+
return b"DSSEv1 %d %b %d %b" % (
|
| 81 |
+
len(payload_type_bytes),
|
| 82 |
+
payload_type_bytes,
|
| 83 |
+
len(payload),
|
| 84 |
+
payload,
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def _verify_hmac_dsse(envelope: Any, key: bytes) -> dict[str, Any]:
|
| 89 |
+
"""Verify a non-stub HMAC-SHA256 DSSE envelope and return its JSON payload."""
|
| 90 |
+
|
| 91 |
+
_require(isinstance(key, bytes) and len(key) >= 32, "receipt HMAC key must contain at least 32 bytes")
|
| 92 |
+
_require(isinstance(envelope, dict), "receipt envelope must be an object")
|
| 93 |
+
_require_exact_keys(envelope, {"payloadType", "payload", "signatures"}, "receipt envelope")
|
| 94 |
+
_require(envelope["payloadType"] == RECEIPT_PAYLOAD_TYPE, "unexpected receipt payload type")
|
| 95 |
+
_require(isinstance(envelope["payload"], str), "receipt payload must be base64 text")
|
| 96 |
+
_require(isinstance(envelope["signatures"], list) and len(envelope["signatures"]) == 1, "exactly one receipt signature is required")
|
| 97 |
+
signature = envelope["signatures"][0]
|
| 98 |
+
_require(isinstance(signature, dict), "receipt signature must be an object")
|
| 99 |
+
_require_exact_keys(signature, {"keyid", "scheme", "sig"}, "receipt signature")
|
| 100 |
+
_require(signature["scheme"] == "hmac-sha256", "stub or unsupported receipt signature scheme")
|
| 101 |
+
_require(isinstance(signature["keyid"], str) and bool(signature["keyid"]), "receipt key id required")
|
| 102 |
+
try:
|
| 103 |
+
payload = base64.b64decode(envelope["payload"], validate=True)
|
| 104 |
+
actual = base64.b64decode(signature["sig"], validate=True)
|
| 105 |
+
except Exception as exc: # pragma: no cover - exact decoder exception is platform-specific
|
| 106 |
+
raise ReceiptRuntimeError("invalid receipt base64") from exc
|
| 107 |
+
expected = hmac.new(key, _dsse_pae(RECEIPT_PAYLOAD_TYPE, payload), hashlib.sha256).digest()
|
| 108 |
+
_require(hmac.compare_digest(actual, expected), "receipt DSSE signature verification failed")
|
| 109 |
+
try:
|
| 110 |
+
value = json.loads(payload.decode("utf-8"))
|
| 111 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 112 |
+
raise ReceiptRuntimeError("receipt payload is not canonical JSON") from exc
|
| 113 |
+
_require(canonical_bytes(value) == payload, "receipt payload is not canonically encoded")
|
| 114 |
+
_require(isinstance(value, dict), "receipt payload must be an object")
|
| 115 |
+
return value
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def _require(condition: bool, message: str) -> None:
|
| 119 |
+
if not condition:
|
| 120 |
+
raise ReceiptRuntimeError(message)
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def _require_exact_keys(value: Mapping[str, Any], keys: set[str], label: str) -> None:
|
| 124 |
+
actual = set(value)
|
| 125 |
+
_require(actual == keys, f"{label} keys mismatch: expected {sorted(keys)}, got {sorted(actual)}")
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def validate_draft(draft: Any) -> None:
|
| 129 |
+
"""Validate the full checked-in draft contract without optional packages."""
|
| 130 |
+
|
| 131 |
+
_require(isinstance(draft, dict), "draft must be an object")
|
| 132 |
+
_require_exact_keys(
|
| 133 |
+
draft,
|
| 134 |
+
{
|
| 135 |
+
"schema_version",
|
| 136 |
+
"status",
|
| 137 |
+
"answer",
|
| 138 |
+
"evidence_ids",
|
| 139 |
+
"formula_refs",
|
| 140 |
+
"uncertainty",
|
| 141 |
+
"abstention",
|
| 142 |
+
"tool_proposal",
|
| 143 |
+
},
|
| 144 |
+
"draft",
|
| 145 |
+
)
|
| 146 |
+
_require(draft["schema_version"] == DRAFT_SCHEMA_VERSION, "unsupported draft schema")
|
| 147 |
+
status = draft["status"]
|
| 148 |
+
_require(status in {"ANSWER_PROPOSED", "ABSTAINED", "UNAVAILABLE"}, "invalid draft status")
|
| 149 |
+
|
| 150 |
+
evidence_ids = draft["evidence_ids"]
|
| 151 |
+
_require(isinstance(evidence_ids, list), "evidence_ids must be an array")
|
| 152 |
+
_require(len(evidence_ids) == len(set(evidence_ids)), "evidence_ids must be unique")
|
| 153 |
+
_require(
|
| 154 |
+
all(isinstance(item, str) and EVIDENCE_ID_RE.fullmatch(item) for item in evidence_ids),
|
| 155 |
+
"invalid evidence id",
|
| 156 |
+
)
|
| 157 |
+
|
| 158 |
+
formula_refs = draft["formula_refs"]
|
| 159 |
+
_require(isinstance(formula_refs, list), "formula_refs must be an array")
|
| 160 |
+
formula_keys: set[tuple[str, str]] = set()
|
| 161 |
+
for index, formula in enumerate(formula_refs):
|
| 162 |
+
_require(isinstance(formula, dict), f"formula_refs[{index}] must be an object")
|
| 163 |
+
_require_exact_keys(formula, {"namespace", "formula_id", "claimed_status"}, f"formula_refs[{index}]")
|
| 164 |
+
namespace = formula["namespace"]
|
| 165 |
+
formula_id = formula["formula_id"]
|
| 166 |
+
_require(isinstance(namespace, str) and bool(namespace), "formula namespace required")
|
| 167 |
+
_require(isinstance(formula_id, str) and bool(formula_id), "formula id required")
|
| 168 |
+
_require(formula["claimed_status"] in FORMULA_STATUS, "invalid claimed formula status")
|
| 169 |
+
key = (namespace, formula_id)
|
| 170 |
+
_require(key not in formula_keys, "formula references must be unique")
|
| 171 |
+
formula_keys.add(key)
|
| 172 |
+
|
| 173 |
+
uncertainty = draft["uncertainty"]
|
| 174 |
+
_require(isinstance(uncertainty, dict), "uncertainty must be an object")
|
| 175 |
+
_require_exact_keys(uncertainty, {"band", "basis"}, "uncertainty")
|
| 176 |
+
_require(uncertainty["band"] in {"LOW", "MEDIUM", "HIGH", "NOT_EVALUATED"}, "invalid uncertainty band")
|
| 177 |
+
_require(isinstance(uncertainty["basis"], str) and bool(uncertainty["basis"]), "uncertainty basis required")
|
| 178 |
+
|
| 179 |
+
abstention = draft["abstention"]
|
| 180 |
+
_require(isinstance(abstention, dict), "abstention must be an object")
|
| 181 |
+
_require_exact_keys(abstention, {"required", "code", "detail"}, "abstention")
|
| 182 |
+
_require(isinstance(abstention["required"], bool), "abstention.required must be boolean")
|
| 183 |
+
_require(abstention["code"] in ABSTENTION_CODES, "invalid abstention code")
|
| 184 |
+
_require(isinstance(abstention["detail"], str) and bool(abstention["detail"]), "abstention detail required")
|
| 185 |
+
|
| 186 |
+
tool = draft["tool_proposal"]
|
| 187 |
+
_require(isinstance(tool, dict), "tool_proposal must be an object")
|
| 188 |
+
_require_exact_keys(tool, {"state", "tool_id", "arguments"}, "tool_proposal")
|
| 189 |
+
_require(tool["state"] in {"NONE", "PROPOSED"}, "invalid tool state")
|
| 190 |
+
if tool["state"] == "NONE":
|
| 191 |
+
_require(tool["tool_id"] is None and tool["arguments"] is None, "NONE tool must have null identity and arguments")
|
| 192 |
+
else:
|
| 193 |
+
_require(status == "ANSWER_PROPOSED", "only an answer proposal may contain a tool proposal")
|
| 194 |
+
_require(isinstance(tool["tool_id"], str) and bool(tool["tool_id"]), "proposed tool id required")
|
| 195 |
+
_require(isinstance(tool["arguments"], dict) and bool(tool["arguments"]), "proposed tool arguments required")
|
| 196 |
+
|
| 197 |
+
if status == "ANSWER_PROPOSED":
|
| 198 |
+
_require(isinstance(draft["answer"], str) and bool(draft["answer"]), "answer proposal requires text")
|
| 199 |
+
_require(bool(evidence_ids), "answer proposal requires evidence")
|
| 200 |
+
_require(uncertainty["band"] in {"LOW", "MEDIUM"}, "answer proposal uncertainty is too high")
|
| 201 |
+
_require(abstention["required"] is False and abstention["code"] == "NONE", "answer proposal cannot abstain")
|
| 202 |
+
elif status == "ABSTAINED":
|
| 203 |
+
_require(draft["answer"] is None, "abstention cannot carry answer text")
|
| 204 |
+
_require(not evidence_ids and not formula_refs, "abstention cannot carry model-selected evidence or formulae")
|
| 205 |
+
_require(uncertainty["band"] == "HIGH", "abstention must report HIGH uncertainty")
|
| 206 |
+
_require(abstention["required"] is True and abstention["code"] not in {"NONE", "MODEL_UNAVAILABLE"}, "invalid abstention state")
|
| 207 |
+
_require(tool["state"] == "NONE", "abstention cannot propose a tool")
|
| 208 |
+
else:
|
| 209 |
+
_require(draft["answer"] is None, "unavailable response cannot carry answer text")
|
| 210 |
+
_require(not evidence_ids and not formula_refs, "unavailable response cannot carry evidence or formulae")
|
| 211 |
+
_require(uncertainty["band"] == "NOT_EVALUATED", "unavailable response must be NOT_EVALUATED")
|
| 212 |
+
_require(abstention["required"] is True and abstention["code"] == "MODEL_UNAVAILABLE", "invalid unavailable state")
|
| 213 |
+
_require(tool["state"] == "NONE", "unavailable response cannot propose a tool")
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
def _validate_model_identity(model_identity: Any) -> dict[str, Any]:
|
| 217 |
+
_require(isinstance(model_identity, dict), "model identity must be an object")
|
| 218 |
+
required = {"candidate_id", "release_state", "base_repository", "base_revision", "adapter_sha256"}
|
| 219 |
+
_require_exact_keys(model_identity, required, "model_identity")
|
| 220 |
+
_require(model_identity["candidate_id"] == CANONICAL_CANDIDATE_ID, "unexpected candidate identity")
|
| 221 |
+
_require(model_identity["release_state"] in {"EXPERIMENTAL", "PROMOTED"}, "a trained runtime identity is required")
|
| 222 |
+
_require(isinstance(model_identity["base_repository"], str) and bool(model_identity["base_repository"]), "base repository required")
|
| 223 |
+
_require(isinstance(model_identity["base_revision"], str) and re.fullmatch(r"[0-9a-f]{40}", model_identity["base_revision"]), "invalid base revision")
|
| 224 |
+
_require(isinstance(model_identity["adapter_sha256"], str) and SHA256_RE.fullmatch(model_identity["adapter_sha256"]), "verified adapter digest required")
|
| 225 |
+
return deepcopy(model_identity)
|
| 226 |
+
|
| 227 |
+
|
| 228 |
+
def _empty_final(
|
| 229 |
+
*,
|
| 230 |
+
draft: Mapping[str, Any],
|
| 231 |
+
request: Any,
|
| 232 |
+
policy_snapshot: Any,
|
| 233 |
+
model_identity: Mapping[str, Any],
|
| 234 |
+
status: str,
|
| 235 |
+
code: str,
|
| 236 |
+
detail: str,
|
| 237 |
+
calibration_state: str,
|
| 238 |
+
) -> dict[str, Any]:
|
| 239 |
+
response_seed = {"draft": draft, "request": request, "policy": policy_snapshot, "model": model_identity}
|
| 240 |
+
return {
|
| 241 |
+
"schema_version": FINAL_SCHEMA_VERSION,
|
| 242 |
+
"response_id": f"response:{canonical_sha256(response_seed)[:24]}",
|
| 243 |
+
"model_identity": deepcopy(model_identity),
|
| 244 |
+
"status": status,
|
| 245 |
+
"answer": None,
|
| 246 |
+
"evidence": [],
|
| 247 |
+
"formulae": [],
|
| 248 |
+
"uncertainty": {
|
| 249 |
+
"confidence": None,
|
| 250 |
+
"calibration_state": calibration_state,
|
| 251 |
+
"basis": draft["uncertainty"]["basis"],
|
| 252 |
+
},
|
| 253 |
+
"abstention": {"required": True, "code": code, "detail": detail},
|
| 254 |
+
"tool_proposal": {
|
| 255 |
+
"state": "NONE",
|
| 256 |
+
"tool_id": None,
|
| 257 |
+
"arguments_sha256": None,
|
| 258 |
+
"requires_human_approval": True,
|
| 259 |
+
"execution_receipt_id": None,
|
| 260 |
+
},
|
| 261 |
+
"receipt_binding": {
|
| 262 |
+
"state": "NOT_AVAILABLE",
|
| 263 |
+
"request_sha256": canonical_sha256(request),
|
| 264 |
+
"evidence_set_sha256": None,
|
| 265 |
+
"policy_snapshot_sha256": canonical_sha256(policy_snapshot),
|
| 266 |
+
"receipt_id": None,
|
| 267 |
+
},
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
def finalize_draft(
|
| 272 |
+
draft: Any,
|
| 273 |
+
*,
|
| 274 |
+
request: Any,
|
| 275 |
+
evidence_catalog: Mapping[str, Mapping[str, Any]],
|
| 276 |
+
formula_catalog: Mapping[str, Mapping[str, Any]],
|
| 277 |
+
policy_snapshot: Mapping[str, Any],
|
| 278 |
+
model_identity: Mapping[str, Any],
|
| 279 |
+
calibration: Mapping[str, Any] | None = None,
|
| 280 |
+
receipt_envelope: Mapping[str, Any] | None = None,
|
| 281 |
+
receipt_hmac_key: bytes | None = None,
|
| 282 |
+
replay_guard: ReceiptReplayGuard | None = None,
|
| 283 |
+
) -> dict[str, Any]:
|
| 284 |
+
"""Resolve an unsigned model draft into a fail-closed final envelope.
|
| 285 |
+
|
| 286 |
+
The receipt must be a canonically encoded DSSE envelope with a valid
|
| 287 |
+
HMAC-SHA256 signature over every decision-bearing component. HMAC is an
|
| 288 |
+
experimental local-runtime mechanism; public promotion still requires an
|
| 289 |
+
asymmetric DSSE/in-toto attestation and transparency-log record.
|
| 290 |
+
"""
|
| 291 |
+
|
| 292 |
+
validate_draft(draft)
|
| 293 |
+
identity = _validate_model_identity(model_identity)
|
| 294 |
+
_require(isinstance(request, (dict, list, str)), "request must be canonical JSON data")
|
| 295 |
+
_require(isinstance(policy_snapshot, dict), "policy snapshot must be an object")
|
| 296 |
+
allowed_tools = policy_snapshot.get("allowed_tool_ids", [])
|
| 297 |
+
_require(isinstance(allowed_tools, list) and all(isinstance(x, str) for x in allowed_tools), "allowed_tool_ids must be strings")
|
| 298 |
+
|
| 299 |
+
if draft["status"] == "UNAVAILABLE":
|
| 300 |
+
return _empty_final(
|
| 301 |
+
draft=draft,
|
| 302 |
+
request=request,
|
| 303 |
+
policy_snapshot=policy_snapshot,
|
| 304 |
+
model_identity=identity,
|
| 305 |
+
status="UNAVAILABLE",
|
| 306 |
+
code="MODEL_UNAVAILABLE",
|
| 307 |
+
detail=draft["abstention"]["detail"],
|
| 308 |
+
calibration_state="NOT_EVALUATED",
|
| 309 |
+
)
|
| 310 |
+
if draft["status"] == "ABSTAINED":
|
| 311 |
+
return _empty_final(
|
| 312 |
+
draft=draft,
|
| 313 |
+
request=request,
|
| 314 |
+
policy_snapshot=policy_snapshot,
|
| 315 |
+
model_identity=identity,
|
| 316 |
+
status="ABSTAINED",
|
| 317 |
+
code=draft["abstention"]["code"],
|
| 318 |
+
detail=draft["abstention"]["detail"],
|
| 319 |
+
calibration_state="UNCALIBRATED",
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
resolved_evidence: list[dict[str, Any]] = []
|
| 323 |
+
for evidence_id in draft["evidence_ids"]:
|
| 324 |
+
record = evidence_catalog.get(evidence_id)
|
| 325 |
+
if not isinstance(record, Mapping):
|
| 326 |
+
return _empty_final(
|
| 327 |
+
draft=draft, request=request, policy_snapshot=policy_snapshot,
|
| 328 |
+
model_identity=identity, status="ABSTAINED", code="EVIDENCE_NOT_ADMITTED",
|
| 329 |
+
detail=f"Evidence {evidence_id} is absent from the immutable admitted snapshot.",
|
| 330 |
+
calibration_state="UNCALIBRATED",
|
| 331 |
+
)
|
| 332 |
+
required = {"content_sha256", "support_role", "admission_state", "freshness_state", "final_evidence_id"}
|
| 333 |
+
if not required.issubset(record):
|
| 334 |
+
raise ReceiptRuntimeError(f"evidence catalog record {evidence_id} is incomplete")
|
| 335 |
+
final_id = record["final_evidence_id"]
|
| 336 |
+
if (
|
| 337 |
+
record["admission_state"] != "ADMITTED_REFERENCE"
|
| 338 |
+
or record["freshness_state"] not in {"CURRENT", "NOT_APPLICABLE"}
|
| 339 |
+
or not isinstance(final_id, str)
|
| 340 |
+
or not FINAL_EVIDENCE_ID_RE.fullmatch(final_id)
|
| 341 |
+
or not isinstance(record["content_sha256"], str)
|
| 342 |
+
or not SHA256_RE.fullmatch(record["content_sha256"])
|
| 343 |
+
or record["support_role"] not in {"SUPPORTS", "CONTRADICTS", "CONTEXT"}
|
| 344 |
+
):
|
| 345 |
+
return _empty_final(
|
| 346 |
+
draft=draft, request=request, policy_snapshot=policy_snapshot,
|
| 347 |
+
model_identity=identity, status="ABSTAINED", code="EVIDENCE_NOT_ADMITTED",
|
| 348 |
+
detail=f"Evidence {evidence_id} failed admission, freshness, or identity validation.",
|
| 349 |
+
calibration_state="UNCALIBRATED",
|
| 350 |
+
)
|
| 351 |
+
item = {
|
| 352 |
+
"evidence_id": final_id,
|
| 353 |
+
"content_sha256": record["content_sha256"],
|
| 354 |
+
"support_role": record["support_role"],
|
| 355 |
+
"admission_state": "ADMITTED_REFERENCE",
|
| 356 |
+
}
|
| 357 |
+
source_uri = record.get("source_uri")
|
| 358 |
+
if source_uri is not None:
|
| 359 |
+
_require(isinstance(source_uri, str) and source_uri.startswith("https://"), "invalid source URI")
|
| 360 |
+
item["source_uri"] = source_uri
|
| 361 |
+
resolved_evidence.append(item)
|
| 362 |
+
|
| 363 |
+
resolved_formulae: list[dict[str, Any]] = []
|
| 364 |
+
for claimed in draft["formula_refs"]:
|
| 365 |
+
key = f"{claimed['namespace']}::{claimed['formula_id']}"
|
| 366 |
+
authoritative = formula_catalog.get(key)
|
| 367 |
+
if not isinstance(authoritative, Mapping) or authoritative.get("status") != claimed["claimed_status"]:
|
| 368 |
+
return _empty_final(
|
| 369 |
+
draft=draft, request=request, policy_snapshot=policy_snapshot,
|
| 370 |
+
model_identity=identity, status="ABSTAINED", code="FORMULA_NAMESPACE_CONFLICT",
|
| 371 |
+
detail=f"Formula reference {key} does not match the authoritative snapshot.",
|
| 372 |
+
calibration_state="UNCALIBRATED",
|
| 373 |
+
)
|
| 374 |
+
receipt_hash = authoritative.get("formula_receipt_sha256")
|
| 375 |
+
semantic_binding = authoritative.get("semantic_binding_sha256")
|
| 376 |
+
proof_allowed = (
|
| 377 |
+
claimed["claimed_status"] == "KERNEL_ACCEPTED"
|
| 378 |
+
and authoritative.get("verification_state") == "KERNEL_VERIFIED"
|
| 379 |
+
and isinstance(receipt_hash, str)
|
| 380 |
+
and bool(SHA256_RE.fullmatch(receipt_hash))
|
| 381 |
+
and isinstance(semantic_binding, str)
|
| 382 |
+
and bool(SHA256_RE.fullmatch(semantic_binding))
|
| 383 |
+
)
|
| 384 |
+
if claimed["claimed_status"] == "KERNEL_ACCEPTED" and not proof_allowed:
|
| 385 |
+
return _empty_final(
|
| 386 |
+
draft=draft, request=request, policy_snapshot=policy_snapshot,
|
| 387 |
+
model_identity=identity, status="ABSTAINED", code="FORMULA_NAMESPACE_CONFLICT",
|
| 388 |
+
detail=f"Formula reference {key} lacks a kernel verification and semantic binding.",
|
| 389 |
+
calibration_state="UNCALIBRATED",
|
| 390 |
+
)
|
| 391 |
+
resolved_formulae.append(
|
| 392 |
+
{
|
| 393 |
+
"formula_id": claimed["formula_id"],
|
| 394 |
+
"namespace": claimed["namespace"],
|
| 395 |
+
"status": claimed["claimed_status"],
|
| 396 |
+
"proof_transfer_allowed": proof_allowed,
|
| 397 |
+
"formula_receipt_sha256": receipt_hash if proof_allowed else None,
|
| 398 |
+
}
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
tool = draft["tool_proposal"]
|
| 402 |
+
if tool["state"] == "PROPOSED" and tool["tool_id"] not in allowed_tools:
|
| 403 |
+
return _empty_final(
|
| 404 |
+
draft=draft, request=request, policy_snapshot=policy_snapshot,
|
| 405 |
+
model_identity=identity, status="ABSTAINED", code="POLICY_DENIED",
|
| 406 |
+
detail=f"Tool {tool['tool_id']} is not allowed by the bound policy snapshot.",
|
| 407 |
+
calibration_state="UNCALIBRATED",
|
| 408 |
+
)
|
| 409 |
+
|
| 410 |
+
if not isinstance(calibration, Mapping):
|
| 411 |
+
return _empty_final(
|
| 412 |
+
draft=draft, request=request, policy_snapshot=policy_snapshot,
|
| 413 |
+
model_identity=identity, status="ABSTAINED", code="UNCERTAINTY_TOO_HIGH",
|
| 414 |
+
detail="No externally measured calibration value is bound to this response.",
|
| 415 |
+
calibration_state="UNCALIBRATED",
|
| 416 |
+
)
|
| 417 |
+
confidence = calibration.get("confidence")
|
| 418 |
+
_require(isinstance(confidence, (int, float)) and not isinstance(confidence, bool) and 0 <= confidence <= 1, "invalid calibrated confidence")
|
| 419 |
+
_require(isinstance(calibration.get("basis"), str) and bool(calibration["basis"]), "calibration basis required")
|
| 420 |
+
|
| 421 |
+
final_tool = {
|
| 422 |
+
"state": tool["state"],
|
| 423 |
+
"tool_id": tool["tool_id"],
|
| 424 |
+
"arguments_sha256": canonical_sha256(tool["arguments"]) if tool["state"] == "PROPOSED" else None,
|
| 425 |
+
"requires_human_approval": True,
|
| 426 |
+
"execution_receipt_id": None,
|
| 427 |
+
}
|
| 428 |
+
evidence_hash = canonical_sha256(sorted(resolved_evidence, key=lambda item: item["evidence_id"]))
|
| 429 |
+
formula_hash = canonical_sha256(sorted(resolved_formulae, key=lambda item: (item["namespace"], item["formula_id"])))
|
| 430 |
+
request_hash = canonical_sha256(request)
|
| 431 |
+
policy_hash = canonical_sha256(policy_snapshot)
|
| 432 |
+
draft_hash = canonical_sha256(draft)
|
| 433 |
+
identity_hash = canonical_sha256(identity)
|
| 434 |
+
calibration_hash = canonical_sha256(calibration)
|
| 435 |
+
tool_hash = canonical_sha256(final_tool)
|
| 436 |
+
binding_payload = {
|
| 437 |
+
"schema_version": "szl.receipt-agent-binding.v1",
|
| 438 |
+
"draft_sha256": draft_hash,
|
| 439 |
+
"answer_sha256": canonical_sha256(draft["answer"]),
|
| 440 |
+
"model_identity_sha256": identity_hash,
|
| 441 |
+
"request_sha256": request_hash,
|
| 442 |
+
"evidence_set_sha256": evidence_hash,
|
| 443 |
+
"formula_set_sha256": formula_hash,
|
| 444 |
+
"calibration_sha256": calibration_hash,
|
| 445 |
+
"tool_proposal_sha256": tool_hash,
|
| 446 |
+
"policy_snapshot_sha256": policy_hash,
|
| 447 |
+
}
|
| 448 |
+
binding_hash = canonical_sha256(binding_payload)
|
| 449 |
+
if receipt_envelope is None or receipt_hmac_key is None or replay_guard is None:
|
| 450 |
+
return _empty_final(
|
| 451 |
+
draft=draft, request=request, policy_snapshot=policy_snapshot,
|
| 452 |
+
model_identity=identity, status="ABSTAINED", code="RECEIPT_INVALID",
|
| 453 |
+
detail="No cryptographically verified, replay-protected receipt binds the complete response payload.",
|
| 454 |
+
calibration_state="CALIBRATED",
|
| 455 |
+
)
|
| 456 |
+
receipt = _verify_hmac_dsse(receipt_envelope, receipt_hmac_key)
|
| 457 |
+
receipt_fields = {
|
| 458 |
+
"schema_version",
|
| 459 |
+
"receipt_id",
|
| 460 |
+
"nonce",
|
| 461 |
+
"binding_payload_sha256",
|
| 462 |
+
"draft_sha256",
|
| 463 |
+
"answer_sha256",
|
| 464 |
+
"model_identity_sha256",
|
| 465 |
+
"request_sha256",
|
| 466 |
+
"evidence_set_sha256",
|
| 467 |
+
"formula_set_sha256",
|
| 468 |
+
"calibration_sha256",
|
| 469 |
+
"tool_proposal_sha256",
|
| 470 |
+
"policy_snapshot_sha256",
|
| 471 |
+
}
|
| 472 |
+
_require_exact_keys(receipt, receipt_fields, "receipt payload")
|
| 473 |
+
_require(receipt["schema_version"] == "szl.receipt-agent-verifier-result.v1", "unsupported receipt result schema")
|
| 474 |
+
_require(isinstance(receipt["receipt_id"], str) and bool(receipt["receipt_id"]), "receipt id required")
|
| 475 |
+
_require(isinstance(receipt["nonce"], str) and len(receipt["nonce"]) >= 16, "receipt nonce required")
|
| 476 |
+
expected_bindings = dict(binding_payload)
|
| 477 |
+
expected_bindings["binding_payload_sha256"] = binding_hash
|
| 478 |
+
for field, expected in expected_bindings.items():
|
| 479 |
+
if field == "schema_version":
|
| 480 |
+
continue
|
| 481 |
+
_require(receipt.get(field) == expected, f"receipt {field} mismatch")
|
| 482 |
+
_require(replay_guard.consume(receipt["receipt_id"]), "receipt replay detected")
|
| 483 |
+
|
| 484 |
+
response_seed = {
|
| 485 |
+
"binding_payload_sha256": binding_hash,
|
| 486 |
+
"receipt_id": receipt["receipt_id"],
|
| 487 |
+
"nonce": receipt["nonce"],
|
| 488 |
+
}
|
| 489 |
+
return {
|
| 490 |
+
"schema_version": FINAL_SCHEMA_VERSION,
|
| 491 |
+
"response_id": f"response:{canonical_sha256(response_seed)[:24]}",
|
| 492 |
+
"model_identity": identity,
|
| 493 |
+
"status": "ANSWERED",
|
| 494 |
+
"answer": draft["answer"],
|
| 495 |
+
"evidence": resolved_evidence,
|
| 496 |
+
"formulae": resolved_formulae,
|
| 497 |
+
"uncertainty": {
|
| 498 |
+
"confidence": confidence,
|
| 499 |
+
"calibration_state": "CALIBRATED",
|
| 500 |
+
"basis": calibration["basis"],
|
| 501 |
+
},
|
| 502 |
+
"abstention": {"required": False, "code": "NONE", "detail": "All deterministic gates passed."},
|
| 503 |
+
"tool_proposal": final_tool,
|
| 504 |
+
"receipt_binding": {
|
| 505 |
+
"state": "SIGNED",
|
| 506 |
+
"request_sha256": request_hash,
|
| 507 |
+
"evidence_set_sha256": evidence_hash,
|
| 508 |
+
"policy_snapshot_sha256": policy_hash,
|
| 509 |
+
"receipt_id": receipt["receipt_id"],
|
| 510 |
+
},
|
| 511 |
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Fixed child used only to attest a fresh Linux network namespace.
|
| 3 |
+
|
| 4 |
+
The parent launches this file through ``unshare --net``. It performs no
|
| 5 |
+
network operation and accepts no command, expression, or package input.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import json
|
| 9 |
+
import os
|
| 10 |
+
import sys
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def main() -> int:
|
| 15 |
+
if len(sys.argv) != 2:
|
| 16 |
+
return 64
|
| 17 |
+
target = Path(sys.argv[1])
|
| 18 |
+
interfaces = sorted(path.name for path in Path("/sys/class/net").iterdir())
|
| 19 |
+
loopback_state = None
|
| 20 |
+
state_path = Path("/sys/class/net/lo/operstate")
|
| 21 |
+
if state_path.is_file():
|
| 22 |
+
loopback_state = state_path.read_text(encoding="utf-8").strip()
|
| 23 |
+
payload = {
|
| 24 |
+
"schema": "szl.numerics.network-namespace-evidence/v1",
|
| 25 |
+
"network_operations_performed": 0,
|
| 26 |
+
"network_namespace": os.readlink("/proc/self/ns/net"),
|
| 27 |
+
"interfaces": interfaces,
|
| 28 |
+
"loopback_operstate": loopback_state,
|
| 29 |
+
}
|
| 30 |
+
target.write_text(
|
| 31 |
+
json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False),
|
| 32 |
+
encoding="utf-8",
|
| 33 |
+
)
|
| 34 |
+
return 0
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
if __name__ == "__main__":
|
| 38 |
+
raise SystemExit(main())
|
|
@@ -1,3 +1,2 @@
|
|
| 1 |
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
"""Research-layer modules for source-cited A11oy experiments."""
|
| 3 |
-
|
|
|
|
| 1 |
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
"""Research-layer modules for source-cited A11oy experiments."""
|
|
|
|
@@ -199,6 +199,268 @@ async def frontier_projects_snapshot() -> JSONResponse:
|
|
| 199 |
return JSONResponse(primary_project_registry_snapshot(fetch_live=False))
|
| 200 |
|
| 201 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
def _optional_module_absent(exc: Exception, module: str, surface: str,
|
| 203 |
*, stream=None) -> bool:
|
| 204 |
"""Log a direct optional-module absence without a noisy traceback.
|
|
@@ -763,8 +1025,8 @@ except Exception as _szl_op_e: # pragma: no cover
|
|
| 763 |
# router, bounded-autonomy AgentLoop, and DSSE receipts. Deliberately drops the tribe's
|
| 764 |
# unbounded "fully agentic" mandate for a11oy's fail-closed Λ-gate. See ayllu/INGEST.md.
|
| 765 |
# Additive, try/except-guarded, same register() pattern. Model backend IS wired via
|
| 766 |
-
# ayllu.backend -> a11oy_code_orchestrator (live
|
| 767 |
-
#
|
| 768 |
try:
|
| 769 |
import a11oy_ayllu as _a11oy_ayllu
|
| 770 |
print("[a11oy] " + _a11oy_ayllu.register(app, ns="a11oy"), file=__import__("sys").stderr)
|
|
@@ -1025,7 +1287,22 @@ except Exception as _szl_brainhealth_e: # pragma: no cover
|
|
| 1025 |
# READ (signs/mints nothing on GET). Adds NOTHING to the locked-8; Λ stays Conjecture 1;
|
| 1026 |
# trust ceiling 0.97. Additive, try/except-guarded, same register() pattern, BEFORE the SPA
|
| 1027 |
# catch-all. Must register AFTER the frontier index (which it reads).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1028 |
try:
|
|
|
|
| 1029 |
import szl_status_aggregate as _szl_status_aggregate
|
| 1030 |
_szl_status_aggregate.register(app, ns="a11oy")
|
| 1031 |
print("[a11oy] Operational STATUS aggregate registered: /api/a11oy/v1/status (honest per-subsystem/surface health, drift-proof)", file=__import__("sys").stderr)
|
|
@@ -2939,12 +3216,6 @@ async def _safe_json_body(request: Request):
|
|
| 2939 |
return None, JSONResponse({"error": "invalid JSON body"}, status_code=400)
|
| 2940 |
|
| 2941 |
|
| 2942 |
-
# ADDITIVE (mesh wire-up, Dev2): cross-pod vsp-otel tracing (W3C traceparent + OTLP/gRPC).
|
| 2943 |
-
try:
|
| 2944 |
-
from vsp_otel.middleware import install as install_vsp; install_vsp(app)
|
| 2945 |
-
except Exception as _vsp_e:
|
| 2946 |
-
import sys as _vsp_sys; print(f"[a11oy] vsp-otel wire skipped: {_vsp_e!r}", file=_vsp_sys.stderr)
|
| 2947 |
-
|
| 2948 |
# ADDITIVE: OTel — instrument FastAPI app
|
| 2949 |
try:
|
| 2950 |
_szl_otel_setup(fastapi_app=app)
|
|
@@ -2963,6 +3234,12 @@ except Exception as _otel_e:
|
|
| 2963 |
try:
|
| 2964 |
import vsp_otel.middleware as _vsp_otel
|
| 2965 |
_vsp_otel.install(app)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2966 |
import sys as _vsp_sys
|
| 2967 |
print(f"[a11oy] vsp-otel VSP installed: exporter={getattr(app, '_vsp_otel_exporter', 'unknown')}", file=_vsp_sys.stderr)
|
| 2968 |
except Exception as _vsp_e:
|
|
@@ -3438,8 +3715,8 @@ except Exception as _formulas_exc: # additive: never break the Space if the mod
|
|
| 3438 |
# in this file, so FastAPI's ordered matching routes /api/a11oy/code/* here
|
| 3439 |
# rather than proxying to Node. Wrapped in try/except so a missing optional dep
|
| 3440 |
# (huggingface_hub / openai) can NEVER take down the existing SPA + gates API.
|
| 3441 |
-
# NO BANDAID: if
|
| 3442 |
-
#
|
| 3443 |
# ---------------------------------------------------------------------------
|
| 3444 |
try:
|
| 3445 |
import a11oy_code_orchestrator as _a11oy_code
|
|
@@ -6685,22 +6962,34 @@ async def a11oy_mcp_call_inline(request: Request):
|
|
| 6685 |
async def a11oy_version():
|
| 6686 |
"""Founder inspection: what build is live, when was it deployed, provenance."""
|
| 6687 |
import os as _szlv_os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6688 |
return {
|
| 6689 |
-
|
| 6690 |
-
"
|
| 6691 |
-
"
|
| 6692 |
-
"
|
| 6693 |
-
"build_time": _szlv_os.getenv("SZL_BUILD_TIME", "2026-06-03T00:00:00Z"),
|
| 6694 |
-
"release_url": "https://github.com/szl-holdings/a11oy/releases/tag/v1.0.0",
|
| 6695 |
"doctrine": "v11",
|
| 6696 |
"kernel_commit": "c7c0ba17",
|
| 6697 |
"p6_status": "SIGNED_OFF",
|
| 6698 |
"p6_grader_score": "14/14",
|
| 6699 |
"p6_sign_off_url": "https://github.com/szl-holdings/szl-holdings/blob/main/SHARED_LEDGER/a11oy/SIGN_OFF.md",
|
| 6700 |
"verify": {
|
| 6701 |
-
"
|
| 6702 |
-
"
|
| 6703 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6704 |
},
|
| 6705 |
# ADDITIVE (waveL Dev2): machine-readable release record of the waves'
|
| 6706 |
# shipped capabilities with HONEST labels. Mirrors CHANGELOG.md; the
|
|
@@ -8106,7 +8395,25 @@ def _a11oy_canonical(obj) -> bytes:
|
|
| 8106 |
def _a11oy_sign_receipt(payload_obj) -> dict:
|
| 8107 |
"""Produce a DSSE envelope over the canonical JSON of payload_obj using the
|
| 8108 |
in-image ephemeral key. Honest UNSIGNED marker if key unavailable."""
|
| 8109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8110 |
to_sign = _a11oy_pae(_A11OY_PAYLOAD_TYPE, body)
|
| 8111 |
env = {
|
| 8112 |
"payloadType": _A11OY_PAYLOAD_TYPE,
|
|
@@ -8114,6 +8421,12 @@ def _a11oy_sign_receipt(payload_obj) -> dict:
|
|
| 8114 |
"_dsse": "DSSEv1",
|
| 8115 |
"_pae_sha256": _hashv2.sha256(to_sign).hexdigest(),
|
| 8116 |
"_signed_at": _dtv2.now(_tzv2.utc).isoformat(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8117 |
}
|
| 8118 |
if _A11OY_PRIV is None:
|
| 8119 |
env["signatures"] = []
|
|
@@ -8126,7 +8439,8 @@ def _a11oy_sign_receipt(payload_obj) -> dict:
|
|
| 8126 |
env["signed"] = True
|
| 8127 |
env["honesty"] = ("REAL — ECDSA-P256-SHA256 over the DSSE PAE, signed by an "
|
| 8128 |
"in-image key generated at server boot. Verify in-browser "
|
| 8129 |
-
"against /cosign.pub; a tampered byte fails.
|
|
|
|
| 8130 |
return env
|
| 8131 |
|
| 8132 |
|
|
@@ -10019,9 +10333,13 @@ except Exception as _kl_e:
|
|
| 10019 |
_LOCAL_ONLY_A11OY_PREFIXES = ("v1/warhacker/", "v1/observability/", "v1/sec/",
|
| 10020 |
"v1/live/", "v1/code/", "v1/seismic/", "v1/feeds/",
|
| 10021 |
"v1/govern/",
|
|
|
|
| 10022 |
"v1/verify/intoto", # in-toto verify guide (DEV2)
|
| 10023 |
"v1/khipu/intoto/", # in-toto receipt views (DEV2)
|
| 10024 |
"v1/vqc/", # Governed VQC (in-process; DEV1)
|
|
|
|
|
|
|
|
|
|
| 10025 |
)
|
| 10026 |
|
| 10027 |
|
|
@@ -12173,8 +12491,8 @@ except Exception as _op_e:
|
|
| 12173 |
|
| 12174 |
# ============================================================================
|
| 12175 |
# SZL-NEMO CORE (Lane I1, 2026-06-14) — OUR sovereign, governed, self-improving
|
| 12176 |
-
# AGENT
|
| 12177 |
-
#
|
| 12178 |
# local-Nemotron-Ultra / a cert. The differentiator is the GOVERNED-MoE
|
| 12179 |
# domain-expert router: "experts" = domain heads (counter-uas / maritime /
|
| 12180 |
# governance / code / finance), routed by a Λ-governed (Conjecture 1, advisory
|
|
@@ -12225,7 +12543,7 @@ except Exception as _nemo_e:
|
|
| 12225 |
# szl_willay_gateway) via their OWN idempotent register() helpers, and adds the
|
| 12226 |
# missing honest GET /api/a11oy/v1/<surface>/status for nemo + qhawaq + waqay +
|
| 12227 |
# yupay + willay. SZL-Nemo /status summarizes a11oy_nemo_core.model_card() (model
|
| 12228 |
-
# = governed
|
| 12229 |
# from-scratch model). Each /status is signed into a Khipu receipt (Conjecture 2).
|
| 12230 |
# Honest LIVE lifecycle (each surface has real runtime substance) with ROADMAP
|
| 12231 |
# sub-items labeled inline. 0 codenames. Front-inserted BEFORE the SPA catch-all.
|
|
|
|
| 199 |
return JSONResponse(primary_project_registry_snapshot(fetch_live=False))
|
| 200 |
|
| 201 |
|
| 202 |
+
# Quantum Utility Gate (wave 16): bounded proposal-only analysis. The core is
|
| 203 |
+
# pure stdlib and has no provider/QPU/network/filesystem/process effectors. It
|
| 204 |
+
# is deliberately separate from the finance szl_gpu_quant engine; the existing
|
| 205 |
+
# szl_vqc surface remains MODELED/SIMULATED and is not hardware evidence.
|
| 206 |
+
try:
|
| 207 |
+
from szl_quantum_utility import (
|
| 208 |
+
ContractError as QuantumUtilityContractError,
|
| 209 |
+
info as quantum_utility_info_payload,
|
| 210 |
+
replay_receipt as quantum_utility_replay,
|
| 211 |
+
run_with_receipt as quantum_utility_run,
|
| 212 |
+
)
|
| 213 |
+
_QUANTUM_UTILITY_READY = True
|
| 214 |
+
except Exception: # pragma: no cover - honest optional degradation
|
| 215 |
+
QuantumUtilityContractError = ValueError # type: ignore[misc,assignment]
|
| 216 |
+
quantum_utility_info_payload = None # type: ignore[assignment]
|
| 217 |
+
quantum_utility_replay = None # type: ignore[assignment]
|
| 218 |
+
quantum_utility_run = None # type: ignore[assignment]
|
| 219 |
+
_QUANTUM_UTILITY_READY = False
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
_QUANTUM_UTILITY_BODY_LIMIT = 256 * 1024
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
class _QuantumUtilityPayloadTooLarge(ValueError):
|
| 226 |
+
pass
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
async def _quantum_utility_body(request: Request) -> dict[str, Any]:
|
| 230 |
+
content_length = request.headers.get("content-length")
|
| 231 |
+
if content_length is not None:
|
| 232 |
+
try:
|
| 233 |
+
declared_length = int(content_length)
|
| 234 |
+
except ValueError as exc:
|
| 235 |
+
raise QuantumUtilityContractError("content-length must be a non-negative integer") from exc
|
| 236 |
+
if declared_length < 0:
|
| 237 |
+
raise QuantumUtilityContractError("content-length must be a non-negative integer")
|
| 238 |
+
if declared_length > _QUANTUM_UTILITY_BODY_LIMIT:
|
| 239 |
+
raise _QuantumUtilityPayloadTooLarge("request body exceeds 256 KiB")
|
| 240 |
+
|
| 241 |
+
body_buffer = bytearray()
|
| 242 |
+
async for chunk in request.stream():
|
| 243 |
+
if len(body_buffer) + len(chunk) > _QUANTUM_UTILITY_BODY_LIMIT:
|
| 244 |
+
raise _QuantumUtilityPayloadTooLarge("request body exceeds 256 KiB")
|
| 245 |
+
body_buffer.extend(chunk)
|
| 246 |
+
body = bytes(body_buffer)
|
| 247 |
+
try:
|
| 248 |
+
value = json.loads(body.decode("utf-8"))
|
| 249 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 250 |
+
raise QuantumUtilityContractError("request body must be one JSON object") from exc
|
| 251 |
+
if not isinstance(value, dict):
|
| 252 |
+
raise QuantumUtilityContractError("request body must be one JSON object")
|
| 253 |
+
return value
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
def _quantum_utility_unavailable() -> JSONResponse:
|
| 257 |
+
return JSONResponse(
|
| 258 |
+
{
|
| 259 |
+
"ready": False,
|
| 260 |
+
"label": "UNAVAILABLE",
|
| 261 |
+
"mode": "UNAVAILABLE",
|
| 262 |
+
"effectors": 0,
|
| 263 |
+
"provider_calls": 0,
|
| 264 |
+
"qpu_calls": 0,
|
| 265 |
+
},
|
| 266 |
+
status_code=503,
|
| 267 |
+
)
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
async def _quantum_utility_operation(request: Request, operation: str) -> JSONResponse:
|
| 271 |
+
if not _QUANTUM_UTILITY_READY or quantum_utility_run is None:
|
| 272 |
+
return _quantum_utility_unavailable()
|
| 273 |
+
try:
|
| 274 |
+
return JSONResponse(quantum_utility_run(operation, await _quantum_utility_body(request)))
|
| 275 |
+
except _QuantumUtilityPayloadTooLarge as exc:
|
| 276 |
+
return JSONResponse(
|
| 277 |
+
{
|
| 278 |
+
"ready": True,
|
| 279 |
+
"label": "STRUCTURAL-ONLY",
|
| 280 |
+
"accepted": False,
|
| 281 |
+
"error": str(exc),
|
| 282 |
+
"mode": "PROPOSAL_ONLY",
|
| 283 |
+
"effectors": 0,
|
| 284 |
+
"provider_calls": 0,
|
| 285 |
+
"qpu_calls": 0,
|
| 286 |
+
},
|
| 287 |
+
status_code=413,
|
| 288 |
+
)
|
| 289 |
+
except QuantumUtilityContractError as exc:
|
| 290 |
+
return JSONResponse(
|
| 291 |
+
{
|
| 292 |
+
"ready": True,
|
| 293 |
+
"label": "STRUCTURAL-ONLY",
|
| 294 |
+
"accepted": False,
|
| 295 |
+
"error": str(exc),
|
| 296 |
+
"mode": "PROPOSAL_ONLY",
|
| 297 |
+
"effectors": 0,
|
| 298 |
+
"provider_calls": 0,
|
| 299 |
+
"qpu_calls": 0,
|
| 300 |
+
},
|
| 301 |
+
status_code=422,
|
| 302 |
+
)
|
| 303 |
+
|
| 304 |
+
|
| 305 |
+
@app.get("/api/a11oy/v1/quantum-utility/info")
|
| 306 |
+
async def quantum_utility_info() -> JSONResponse:
|
| 307 |
+
if not _QUANTUM_UTILITY_READY or quantum_utility_info_payload is None:
|
| 308 |
+
return _quantum_utility_unavailable()
|
| 309 |
+
return JSONResponse(quantum_utility_info_payload())
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
@app.post("/api/a11oy/v1/quantum-utility/qubo/baseline")
|
| 313 |
+
async def quantum_utility_qubo_baseline(request: Request) -> JSONResponse:
|
| 314 |
+
return await _quantum_utility_operation(request, "QUBO_EXACT_BASELINE")
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
@app.post("/api/a11oy/v1/quantum-utility/hamiltonian/shot-plan")
|
| 318 |
+
async def quantum_utility_hamiltonian_shot_plan(request: Request) -> JSONResponse:
|
| 319 |
+
return await _quantum_utility_operation(request, "HAMILTONIAN_SHOT_PLAN")
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
@app.post("/api/a11oy/v1/quantum-utility/counterfactual/score")
|
| 323 |
+
async def quantum_utility_counterfactual_score(request: Request) -> JSONResponse:
|
| 324 |
+
return await _quantum_utility_operation(request, "COUNTERFACTUAL_SCORE")
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
@app.post("/api/a11oy/v1/quantum-utility/claim/rupture-gate")
|
| 328 |
+
async def quantum_utility_claim_gate(request: Request) -> JSONResponse:
|
| 329 |
+
return await _quantum_utility_operation(request, "QUANTUM_ADVANTAGE_GATE")
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
@app.post("/api/a11oy/v1/quantum-utility/receipt/replay")
|
| 333 |
+
async def quantum_utility_receipt_replay(request: Request) -> JSONResponse:
|
| 334 |
+
if not _QUANTUM_UTILITY_READY or quantum_utility_replay is None:
|
| 335 |
+
return _quantum_utility_unavailable()
|
| 336 |
+
try:
|
| 337 |
+
return JSONResponse(quantum_utility_replay(await _quantum_utility_body(request)))
|
| 338 |
+
except _QuantumUtilityPayloadTooLarge as exc:
|
| 339 |
+
return JSONResponse(
|
| 340 |
+
{
|
| 341 |
+
"ready": True,
|
| 342 |
+
"label": "STRUCTURAL-ONLY",
|
| 343 |
+
"valid": False,
|
| 344 |
+
"error": str(exc),
|
| 345 |
+
"mode": "PROPOSAL_ONLY",
|
| 346 |
+
"effectors": 0,
|
| 347 |
+
"provider_calls": 0,
|
| 348 |
+
"qpu_calls": 0,
|
| 349 |
+
},
|
| 350 |
+
status_code=413,
|
| 351 |
+
)
|
| 352 |
+
except QuantumUtilityContractError as exc:
|
| 353 |
+
return JSONResponse(
|
| 354 |
+
{
|
| 355 |
+
"ready": True,
|
| 356 |
+
"label": "STRUCTURAL-ONLY",
|
| 357 |
+
"valid": False,
|
| 358 |
+
"error": str(exc),
|
| 359 |
+
"mode": "PROPOSAL_ONLY",
|
| 360 |
+
"effectors": 0,
|
| 361 |
+
"provider_calls": 0,
|
| 362 |
+
"qpu_calls": 0,
|
| 363 |
+
},
|
| 364 |
+
status_code=422,
|
| 365 |
+
)
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
# External numerical-engine frontier (wave 18). The module accepts only fixed
|
| 369 |
+
# matrix solve, symmetric-eigenvalue, and reference-vector operations. GNU
|
| 370 |
+
# Octave and MATLAB remain external installations; missing engine, offline
|
| 371 |
+
# license configuration, POSIX resource limits, or network isolation reports
|
| 372 |
+
# UNAVAILABLE. Results are unsigned deterministic digests with zero proof/trust
|
| 373 |
+
# uplift. Registration is early so these routes precede both catch-alls.
|
| 374 |
+
try:
|
| 375 |
+
import szl_numerics_adapter as _szl_numerics_adapter
|
| 376 |
+
|
| 377 |
+
_NUMERICS_ADAPTER_STATUS = _szl_numerics_adapter.register(app, ns="a11oy")
|
| 378 |
+
except Exception as _numerics_adapter_error: # pragma: no cover - honest optional degradation
|
| 379 |
+
_NUMERICS_ADAPTER_STATUS = {
|
| 380 |
+
"registered": False,
|
| 381 |
+
"state": "UNAVAILABLE",
|
| 382 |
+
"reason": type(_numerics_adapter_error).__name__,
|
| 383 |
+
"proof_uplift": 0,
|
| 384 |
+
"trust_uplift": 0,
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
# Yupaq governed computation plane (wave 23). This is the strict binding layer
|
| 389 |
+
# over the existing Quant, Quantum Utility, MATLAB/Octave, Lean/mathlib,
|
| 390 |
+
# formula-admission, Brain, Lambda, OTel, and SZL-Lake organs. It accepts only
|
| 391 |
+
# fixed typed operations; arbitrary code, paths, URLs, packages, provider
|
| 392 |
+
# credentials, and shell arguments are structurally impossible. Registration
|
| 393 |
+
# remains early so the local routes precede both proxy and SPA catch-alls.
|
| 394 |
+
try:
|
| 395 |
+
import szl_yupaq_compute as _szl_yupaq_compute
|
| 396 |
+
|
| 397 |
+
_YUPAQ_COMPUTE_STATUS = _szl_yupaq_compute.register(app, ns="a11oy")
|
| 398 |
+
except Exception as _yupaq_compute_error: # pragma: no cover - honest optional degradation
|
| 399 |
+
_YUPAQ_COMPUTE_STATUS = {
|
| 400 |
+
"registered": False,
|
| 401 |
+
"state": "UNAVAILABLE",
|
| 402 |
+
"reason": type(_yupaq_compute_error).__name__,
|
| 403 |
+
"proof_uplift": 0,
|
| 404 |
+
"trust_uplift": 0,
|
| 405 |
+
}
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
# Preregistered numerical evaluator dataset (wave 22). This is a separate
|
| 409 |
+
# evidence surface from engine execution: 1,328 deterministic case definitions
|
| 410 |
+
# are read-only; authenticated run receipts append to an integrity-linked
|
| 411 |
+
# ledger. Missing engines, reference evidence, network denial, or licensing
|
| 412 |
+
# evidence remain UNAVAILABLE/NOT_EVALUATED and never become synthetic results.
|
| 413 |
+
try:
|
| 414 |
+
import szl_numerics_dataset as _szl_numerics_dataset
|
| 415 |
+
|
| 416 |
+
_NUMERICS_DATASET_STATUS = _szl_numerics_dataset.register(app, ns="a11oy")
|
| 417 |
+
except Exception as _numerics_dataset_error: # pragma: no cover - honest optional degradation
|
| 418 |
+
_NUMERICS_DATASET_STATUS = {
|
| 419 |
+
"registered": False,
|
| 420 |
+
"state": "UNAVAILABLE",
|
| 421 |
+
"reason": type(_numerics_dataset_error).__name__,
|
| 422 |
+
"proof_uplift": 0,
|
| 423 |
+
"trust_uplift": 0,
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
|
| 427 |
+
# Formal Conjecture Lab (wave 19). Declarations and formal artifacts are
|
| 428 |
+
# bounded local writes. No prover command is exposed. A transition to a kernel
|
| 429 |
+
# result requires an externally produced DSSE receipt verified against the
|
| 430 |
+
# embedded public cosign key and bound to the exact server-computed statement
|
| 431 |
+
# and artifact hashes. KERNEL_ACCEPTED is evidence only, never proof promotion.
|
| 432 |
+
try:
|
| 433 |
+
import szl_formal_conjecture_lab as _szl_formal_conjecture_lab
|
| 434 |
+
|
| 435 |
+
_FORMAL_CONJECTURE_LAB_STATUS = _szl_formal_conjecture_lab.register(app, ns="a11oy")
|
| 436 |
+
except Exception as _formal_conjecture_lab_error: # pragma: no cover - honest optional degradation
|
| 437 |
+
_FORMAL_CONJECTURE_LAB_STATUS = {
|
| 438 |
+
"registered": False,
|
| 439 |
+
"kernel_execution": "UNAVAILABLE",
|
| 440 |
+
"proof_promotion": "DISABLED",
|
| 441 |
+
"reason": type(_formal_conjecture_lab_error).__name__,
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
|
| 445 |
+
# M1 experimental model operational gate (wave 22). The candidate remains
|
| 446 |
+
# NOT_PROMOTED and no weights are bundled. The module front-moves its exact
|
| 447 |
+
# status/infer/page routes ahead of both catch-alls and runs only a local,
|
| 448 |
+
# bounded PEFT turn after byte-exact artifact/receipt verification, GPU
|
| 449 |
+
# admission, and provider-identity binding. Missing evidence reports structured
|
| 450 |
+
# BLOCKED/UNAVAILABLE; there is no remote-provider or download fallback.
|
| 451 |
+
try:
|
| 452 |
+
import szl_m1_model_gate as _szl_m1_model_gate
|
| 453 |
+
|
| 454 |
+
_M1_MODEL_GATE_STATUS = _szl_m1_model_gate.register(app, ns="a11oy")
|
| 455 |
+
except Exception as _m1_model_gate_error: # pragma: no cover - honest optional degradation
|
| 456 |
+
_M1_MODEL_GATE_STATUS = {
|
| 457 |
+
"registered": False,
|
| 458 |
+
"operational_state": "UNAVAILABLE",
|
| 459 |
+
"release_state": "NOT_PROMOTED",
|
| 460 |
+
"production_eligible": False,
|
| 461 |
+
"reason": type(_m1_model_gate_error).__name__,
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
def _optional_module_absent(exc: Exception, module: str, surface: str,
|
| 465 |
*, stream=None) -> bool:
|
| 466 |
"""Log a direct optional-module absence without a noisy traceback.
|
|
|
|
| 1025 |
# router, bounded-autonomy AgentLoop, and DSSE receipts. Deliberately drops the tribe's
|
| 1026 |
# unbounded "fully agentic" mandate for a11oy's fail-closed Λ-gate. See ayllu/INGEST.md.
|
| 1027 |
# Additive, try/except-guarded, same register() pattern. Model backend IS wired via
|
| 1028 |
+
# ayllu.backend -> a11oy_code_orchestrator (live when a local endpoint answers or a
|
| 1029 |
+
# remote credential is present; a clearly-labeled deterministic stub otherwise).
|
| 1030 |
try:
|
| 1031 |
import a11oy_ayllu as _a11oy_ayllu
|
| 1032 |
print("[a11oy] " + _a11oy_ayllu.register(app, ns="a11oy"), file=__import__("sys").stderr)
|
|
|
|
| 1287 |
# READ (signs/mints nothing on GET). Adds NOTHING to the locked-8; Λ stays Conjecture 1;
|
| 1288 |
# trust ceiling 0.97. Additive, try/except-guarded, same register() pattern, BEFORE the SPA
|
| 1289 |
# catch-all. Must register AFTER the frontier index (which it reads).
|
| 1290 |
+
# BRAIN EVIDENCE RERANKER + OUROBOROS LOCAL FEED (wave 22). This is a
|
| 1291 |
+
# readiness/data boundary, not a trainer. It inventories every raw Brain node,
|
| 1292 |
+
# requires canonical content-addressed corpus manifests before admitting rows,
|
| 1293 |
+
# and reports dataset, evaluation, and model readiness independently. The local
|
| 1294 |
+
# feed write path is loopback-only, bounded, checkpointed, and kill-switched.
|
| 1295 |
+
try:
|
| 1296 |
+
import szl_brain_reranker as _szl_brain_reranker
|
| 1297 |
+
_brain_reranker_paths = _szl_brain_reranker.register(app, ns="a11oy")
|
| 1298 |
+
print(f"[a11oy] Brain evidence-reranker registered: {_brain_reranker_paths}",
|
| 1299 |
+
file=__import__("sys").stderr)
|
| 1300 |
+
except Exception as _szl_brain_reranker_e: # pragma: no cover
|
| 1301 |
+
print(f"[a11oy] Brain evidence-reranker NOT registered: {_szl_brain_reranker_e!r}; "
|
| 1302 |
+
"SPA + API unaffected", file=__import__("sys").stderr)
|
| 1303 |
+
|
| 1304 |
try:
|
| 1305 |
+
# Status aggregate remains registered after the evidence-reranker block above.
|
| 1306 |
import szl_status_aggregate as _szl_status_aggregate
|
| 1307 |
_szl_status_aggregate.register(app, ns="a11oy")
|
| 1308 |
print("[a11oy] Operational STATUS aggregate registered: /api/a11oy/v1/status (honest per-subsystem/surface health, drift-proof)", file=__import__("sys").stderr)
|
|
|
|
| 3216 |
return None, JSONResponse({"error": "invalid JSON body"}, status_code=400)
|
| 3217 |
|
| 3218 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3219 |
# ADDITIVE: OTel — instrument FastAPI app
|
| 3220 |
try:
|
| 3221 |
_szl_otel_setup(fastapi_app=app)
|
|
|
|
| 3234 |
try:
|
| 3235 |
import vsp_otel.middleware as _vsp_otel
|
| 3236 |
_vsp_otel.install(app)
|
| 3237 |
+
app.add_api_route(
|
| 3238 |
+
"/api/a11oy/v1/observability/status",
|
| 3239 |
+
lambda: JSONResponse(_vsp_otel.status(app)),
|
| 3240 |
+
methods=["GET"],
|
| 3241 |
+
include_in_schema=False,
|
| 3242 |
+
)
|
| 3243 |
import sys as _vsp_sys
|
| 3244 |
print(f"[a11oy] vsp-otel VSP installed: exporter={getattr(app, '_vsp_otel_exporter', 'unknown')}", file=_vsp_sys.stderr)
|
| 3245 |
except Exception as _vsp_e:
|
|
|
|
| 3715 |
# in this file, so FastAPI's ordered matching routes /api/a11oy/code/* here
|
| 3716 |
# rather than proxying to Node. Wrapped in try/except so a missing optional dep
|
| 3717 |
# (huggingface_hub / openai) can NEVER take down the existing SPA + gates API.
|
| 3718 |
+
# NO BANDAID: if neither a reachable local endpoint nor a credentialed remote
|
| 3719 |
+
# provider is available, the orchestrator refuses or emits its labeled stub.
|
| 3720 |
# ---------------------------------------------------------------------------
|
| 3721 |
try:
|
| 3722 |
import a11oy_code_orchestrator as _a11oy_code
|
|
|
|
| 6962 |
async def a11oy_version():
|
| 6963 |
"""Founder inspection: what build is live, when was it deployed, provenance."""
|
| 6964 |
import os as _szlv_os
|
| 6965 |
+
from szl_release_identity import release_identity as _release_identity
|
| 6966 |
+
|
| 6967 |
+
_identity = _release_identity()
|
| 6968 |
+
_release_tag = _identity.get("release_tag")
|
| 6969 |
+
_release_assets_ready = bool(_release_tag)
|
| 6970 |
return {
|
| 6971 |
+
**_identity,
|
| 6972 |
+
"git_sha": _szlv_os.getenv("SZL_GIT_SHA") or "UNKNOWN",
|
| 6973 |
+
"hf_space_sha": _szlv_os.getenv("SZL_HF_SHA") or "UNKNOWN",
|
| 6974 |
+
"build_time": _szlv_os.getenv("SZL_BUILD_TIME") or "UNKNOWN",
|
|
|
|
|
|
|
| 6975 |
"doctrine": "v11",
|
| 6976 |
"kernel_commit": "c7c0ba17",
|
| 6977 |
"p6_status": "SIGNED_OFF",
|
| 6978 |
"p6_grader_score": "14/14",
|
| 6979 |
"p6_sign_off_url": "https://github.com/szl-holdings/szl-holdings/blob/main/SHARED_LEDGER/a11oy/SIGN_OFF.md",
|
| 6980 |
"verify": {
|
| 6981 |
+
"release_assets_status": "CONFIGURED_UNVERIFIED" if _release_assets_ready else "PENDING_RELEASE",
|
| 6982 |
+
"cosign": (
|
| 6983 |
+
f"cosign verify ghcr.io/szl-holdings/a11oy:{_release_tag} --certificate-identity-regexp=szl-holdings"
|
| 6984 |
+
if _release_assets_ready
|
| 6985 |
+
else None
|
| 6986 |
+
),
|
| 6987 |
+
"sbom": (
|
| 6988 |
+
f"https://github.com/szl-holdings/a11oy/releases/download/{_release_tag}/a11oy-sbom.cdx.json"
|
| 6989 |
+
if _release_assets_ready
|
| 6990 |
+
else None
|
| 6991 |
+
),
|
| 6992 |
+
"honest": "https://a-11-oy.com/api/a11oy/v1/honest",
|
| 6993 |
},
|
| 6994 |
# ADDITIVE (waveL Dev2): machine-readable release record of the waves'
|
| 6995 |
# shipped capabilities with HONEST labels. Mirrors CHANGELOG.md; the
|
|
|
|
| 8395 |
def _a11oy_sign_receipt(payload_obj) -> dict:
|
| 8396 |
"""Produce a DSSE envelope over the canonical JSON of payload_obj using the
|
| 8397 |
in-image ephemeral key. Honest UNSIGNED marker if key unavailable."""
|
| 8398 |
+
key_identity = {
|
| 8399 |
+
"keyid": _A11OY_KEYID,
|
| 8400 |
+
"verify_key_url": "/api/a11oy/cosign.pub",
|
| 8401 |
+
"key_scope": "PROCESS_BOOT_EPHEMERAL",
|
| 8402 |
+
"key_lifetime": "UNTIL_PROCESS_RESTART",
|
| 8403 |
+
"key_fingerprint_sha256": (
|
| 8404 |
+
_hashv2.sha256((_A11OY_PUB_PEM or "").strip().encode()).hexdigest()
|
| 8405 |
+
if _A11OY_PUB_PEM else None
|
| 8406 |
+
),
|
| 8407 |
+
}
|
| 8408 |
+
# Key discovery is part of the signed statement, not mutable envelope-only
|
| 8409 |
+
# metadata. Verifiers must pin this same-origin URL and compare the fetched
|
| 8410 |
+
# key fingerprint with this signed value before accepting a signature.
|
| 8411 |
+
if isinstance(payload_obj, dict):
|
| 8412 |
+
signed_payload = dict(payload_obj)
|
| 8413 |
+
else:
|
| 8414 |
+
signed_payload = {"value": payload_obj}
|
| 8415 |
+
signed_payload["_signing_identity"] = key_identity
|
| 8416 |
+
body = _a11oy_canonical(signed_payload)
|
| 8417 |
to_sign = _a11oy_pae(_A11OY_PAYLOAD_TYPE, body)
|
| 8418 |
env = {
|
| 8419 |
"payloadType": _A11OY_PAYLOAD_TYPE,
|
|
|
|
| 8421 |
"_dsse": "DSSEv1",
|
| 8422 |
"_pae_sha256": _hashv2.sha256(to_sign).hexdigest(),
|
| 8423 |
"_signed_at": _dtv2.now(_tzv2.utc).isoformat(),
|
| 8424 |
+
# Duplicated for operator ergonomics; the authoritative values are the
|
| 8425 |
+
# identical fields inside the signed payload's _signing_identity.
|
| 8426 |
+
"verify_key_url": key_identity["verify_key_url"],
|
| 8427 |
+
"key_scope": key_identity["key_scope"],
|
| 8428 |
+
"key_lifetime": key_identity["key_lifetime"],
|
| 8429 |
+
"key_fingerprint_sha256": key_identity["key_fingerprint_sha256"],
|
| 8430 |
}
|
| 8431 |
if _A11OY_PRIV is None:
|
| 8432 |
env["signatures"] = []
|
|
|
|
| 8439 |
env["signed"] = True
|
| 8440 |
env["honesty"] = ("REAL — ECDSA-P256-SHA256 over the DSSE PAE, signed by an "
|
| 8441 |
"in-image key generated at server boot. Verify in-browser "
|
| 8442 |
+
"against /api/a11oy/cosign.pub; a tampered byte fails. "
|
| 8443 |
+
"Key resets on process restart.")
|
| 8444 |
return env
|
| 8445 |
|
| 8446 |
|
|
|
|
| 10333 |
_LOCAL_ONLY_A11OY_PREFIXES = ("v1/warhacker/", "v1/observability/", "v1/sec/",
|
| 10334 |
"v1/live/", "v1/code/", "v1/seismic/", "v1/feeds/",
|
| 10335 |
"v1/govern/",
|
| 10336 |
+
"v1/models/m1", # M1 local-only experimental gate
|
| 10337 |
"v1/verify/intoto", # in-toto verify guide (DEV2)
|
| 10338 |
"v1/khipu/intoto/", # in-toto receipt views (DEV2)
|
| 10339 |
"v1/vqc/", # Governed VQC (in-process; DEV1)
|
| 10340 |
+
"v1/quantum-utility/", # Proposal-only Quantum Utility Gate
|
| 10341 |
+
"v1/compute/", # Yupaq governed computation plane
|
| 10342 |
+
"v1/formal-conjecture-lab/", # Fail-closed formal receipt lab
|
| 10343 |
)
|
| 10344 |
|
| 10345 |
|
|
|
|
| 12491 |
|
| 12492 |
# ============================================================================
|
| 12493 |
# SZL-NEMO CORE (Lane I1, 2026-06-14) — OUR sovereign, governed, self-improving
|
| 12494 |
+
# AGENT RUNTIME built on the exact public Nemotron 3 Nano 4B recipe and registry
|
| 12495 |
+
# manifest. NEVER claims SZL fine-tuning / from-scratch / 550B /
|
| 12496 |
# local-Nemotron-Ultra / a cert. The differentiator is the GOVERNED-MoE
|
| 12497 |
# domain-expert router: "experts" = domain heads (counter-uas / maritime /
|
| 12498 |
# governance / code / finance), routed by a Λ-governed (Conjecture 1, advisory
|
|
|
|
| 12543 |
# szl_willay_gateway) via their OWN idempotent register() helpers, and adds the
|
| 12544 |
# missing honest GET /api/a11oy/v1/<surface>/status for nemo + qhawaq + waqay +
|
| 12545 |
# yupay + willay. SZL-Nemo /status summarizes a11oy_nemo_core.model_card() (model
|
| 12546 |
+
# = governed Nemotron 3 Nano 4B recipe, served only after exact runtime identity; NEVER a
|
| 12547 |
# from-scratch model). Each /status is signed into a Khipu receipt (Conjecture 2).
|
| 12548 |
# Honest LIVE lifecycle (each surface has real runtime substance) with ROADMAP
|
| 12549 |
# sub-items labeled inline. 0 codenames. Front-inserted BEFORE the SPA catch-all.
|
|
@@ -132,6 +132,7 @@ SURFACES: List[Dict[str, str]] = [
|
|
| 132 |
{"id": "agentops", "cat": "reasoning", "title": "Agent Ops · bounded operate loop (ground→act→self-eval→gate, Ouroboros-bounded, writer≠judge)", "owner": "WaveP-Dev5"},
|
| 133 |
{"id": "lgmi", "cat": "governance", "title": "LGMI · Λ-Governed Mechanistic Interpretability (synthesis)", "owner": "WaveP-Dev4"},
|
| 134 |
{"id": "gnqs", "cat": "quant", "title": "GNQS · Governed-Norm Quantization Stability (synthesis)", "owner": "WaveP-Dev4"},
|
|
|
|
| 135 |
{"id": "casta", "cat": "defense", "title": "CASTA · Clean-room Anomaly × Streaming Test-time Adaptation (synthesis)", "owner": "WaveP-Dev4"},
|
| 136 |
{"id": "frontierindex", "cat": "brain", "title": "Frontier Index · honest ecosystem catalog · per-surface backend label + citations + native/fallback (self-audited)", "owner": "WaveQ-Dev5"},
|
| 137 |
{"id": "sparsemoe", "cat": "quant", "title": "Extreme-Sparsity MoE Analyzer · activation-ratio ↔ inference-cost tradeoff (STRUCTURAL-ONLY)", "owner": "WaveP-Dev4"},
|
|
@@ -151,6 +152,7 @@ SURFACES: List[Dict[str, str]] = [
|
|
| 151 |
{"id": "braincontradict", "cat": "brain", "flag": True, "title": "Brain Contradiction Detector · surfaces potential contradictions between grounded knowledge-graph claims HONESTLY via transparent deterministic heuristics (negation polarity / antonym opposition / numeric conflict) → NO-CONFLICT/POSSIBLE-CONFLICT/CONFLICT-FLAGGED · PRESENTS conflicts, NEVER resolves them (adjudication=human-required), unsigned SHA-256 receipt-on-write (MODELED)", "owner": "WaveS-Dev8"},
|
| 152 |
{"id": "brainuncertainty", "cat": "brain", "title": "Brain Uncertainty · calibrated honest uncertainty on a brain retrieval · reads the same honest ranked retrieval and derives score dispersion + retrieval entropy + rank stability → one uncertainty in [0,1] with a CONFIDENT/UNCERTAIN/HIGHLY-UNCERTAIN verdict (recommends abstain), never CONFIDENT when dispersion/entropy high, MODELED calibration honesty not a probability, unsigned SHA-256 receipt-on-write", "owner": "WaveS-Dev8"},
|
| 153 |
{"id": "brainhealth", "cat": "brain", "title": "Brain Health · live \"can the brain be trusted for this query right now?\" rollup · reads each brain-honesty surface's OWN label VERBATIM (grounding, freshness, provenance, contradiction, uncertainty), degrades absent siblings to UNAVAILABLE → TRUSTWORTHY/DEGRADED/UNTRUSTWORTHY/INSUFFICIENT-SIGNAL, never TRUSTWORTHY if any available component abstains, unsigned SHA-256 receipt-on-write (MODELED)", "owner": "WaveS-Dev8"},
|
|
|
|
| 154 |
{"id": "brainwatch", "cat": "brain", "title": "Brain Watch · knowledge-graph honesty-posture drift monitor · MEASURED label-distribution/orphan/community/salience snapshot vs a caller-supplied PRIOR → STABLE/DRIFTING/DEGRADED/BASELINE-ONLY (no fabricated trend without a real prior), unsigned SHA-256 receipt-on-write", "owner": "WaveT-Dev1"},
|
| 155 |
{"id": "brainconsensus", "cat": "brain", "title": "Brain Consensus · honest corroboration of a brain grounding · measures how MANY distinct nodes support a query and how many distinct communities they span (cross-community agreement is stronger than one clique) → CORROBORATED/WEAK-CORROBORATION/SINGLE-SOURCE, single-source-risk flag when support collapses to one node/community, never CORROBORATED while that flag is set, MODELED corroboration honesty not a truth guarantee, unsigned SHA-256 receipt-on-write", "owner": "WaveU-Dev1"},
|
| 156 |
{"id": "brainqueryaudit", "cat": "brain", "title": "Brain Query Audit · append-only hash-linked ledger of brain queries + the honest verdict each returned · POST appends {query, verdict, grounding_label} and mints an UNSIGNED SHA-256 receipt chained to the prior entry (tamper-evident); GET recomputes the whole chain → CHAIN-INTACT/CHAIN-BROKEN (never softened), ephemeral in-memory ledger labelled honestly, MODELED, receipt-on-write-not-on-read", "owner": "WaveT-Dev1"},
|
|
|
|
| 132 |
{"id": "agentops", "cat": "reasoning", "title": "Agent Ops · bounded operate loop (ground→act→self-eval→gate, Ouroboros-bounded, writer≠judge)", "owner": "WaveP-Dev5"},
|
| 133 |
{"id": "lgmi", "cat": "governance", "title": "LGMI · Λ-Governed Mechanistic Interpretability (synthesis)", "owner": "WaveP-Dev4"},
|
| 134 |
{"id": "gnqs", "cat": "quant", "title": "GNQS · Governed-Norm Quantization Stability (synthesis)", "owner": "WaveP-Dev4"},
|
| 135 |
+
{"id": "numericsdataset", "cat": "quant", "title": "Numerics Dataset · 1,328 frozen matrix cases + append-only engine evidence · preregistered inputs are never shown as measured results · MATCH/CONFLICT/UNAVAILABLE · proof uplift=0", "owner": "Wave18"},
|
| 136 |
{"id": "casta", "cat": "defense", "title": "CASTA · Clean-room Anomaly × Streaming Test-time Adaptation (synthesis)", "owner": "WaveP-Dev4"},
|
| 137 |
{"id": "frontierindex", "cat": "brain", "title": "Frontier Index · honest ecosystem catalog · per-surface backend label + citations + native/fallback (self-audited)", "owner": "WaveQ-Dev5"},
|
| 138 |
{"id": "sparsemoe", "cat": "quant", "title": "Extreme-Sparsity MoE Analyzer · activation-ratio ↔ inference-cost tradeoff (STRUCTURAL-ONLY)", "owner": "WaveP-Dev4"},
|
|
|
|
| 152 |
{"id": "braincontradict", "cat": "brain", "flag": True, "title": "Brain Contradiction Detector · surfaces potential contradictions between grounded knowledge-graph claims HONESTLY via transparent deterministic heuristics (negation polarity / antonym opposition / numeric conflict) → NO-CONFLICT/POSSIBLE-CONFLICT/CONFLICT-FLAGGED · PRESENTS conflicts, NEVER resolves them (adjudication=human-required), unsigned SHA-256 receipt-on-write (MODELED)", "owner": "WaveS-Dev8"},
|
| 153 |
{"id": "brainuncertainty", "cat": "brain", "title": "Brain Uncertainty · calibrated honest uncertainty on a brain retrieval · reads the same honest ranked retrieval and derives score dispersion + retrieval entropy + rank stability → one uncertainty in [0,1] with a CONFIDENT/UNCERTAIN/HIGHLY-UNCERTAIN verdict (recommends abstain), never CONFIDENT when dispersion/entropy high, MODELED calibration honesty not a probability, unsigned SHA-256 receipt-on-write", "owner": "WaveS-Dev8"},
|
| 154 |
{"id": "brainhealth", "cat": "brain", "title": "Brain Health · live \"can the brain be trusted for this query right now?\" rollup · reads each brain-honesty surface's OWN label VERBATIM (grounding, freshness, provenance, contradiction, uncertainty), degrades absent siblings to UNAVAILABLE → TRUSTWORTHY/DEGRADED/UNTRUSTWORTHY/INSUFFICIENT-SIGNAL, never TRUSTWORTHY if any available component abstains, unsigned SHA-256 receipt-on-write (MODELED)", "owner": "WaveS-Dev8"},
|
| 155 |
+
{"id": "brainreranker", "cat": "brain", "flag": True, "title": "Anatomy v6 · Brain evidence inventory, reranker readiness, and bounded Ouroboros local-feed receipts · every raw node receives an admission/quarantine decision · zero proposal rows while canonical manifests are absent", "owner": "Wave22-Brain-Evidence"},
|
| 156 |
{"id": "brainwatch", "cat": "brain", "title": "Brain Watch · knowledge-graph honesty-posture drift monitor · MEASURED label-distribution/orphan/community/salience snapshot vs a caller-supplied PRIOR → STABLE/DRIFTING/DEGRADED/BASELINE-ONLY (no fabricated trend without a real prior), unsigned SHA-256 receipt-on-write", "owner": "WaveT-Dev1"},
|
| 157 |
{"id": "brainconsensus", "cat": "brain", "title": "Brain Consensus · honest corroboration of a brain grounding · measures how MANY distinct nodes support a query and how many distinct communities they span (cross-community agreement is stronger than one clique) → CORROBORATED/WEAK-CORROBORATION/SINGLE-SOURCE, single-source-risk flag when support collapses to one node/community, never CORROBORATED while that flag is set, MODELED corroboration honesty not a truth guarantee, unsigned SHA-256 receipt-on-write", "owner": "WaveU-Dev1"},
|
| 158 |
{"id": "brainqueryaudit", "cat": "brain", "title": "Brain Query Audit · append-only hash-linked ledger of brain queries + the honest verdict each returned · POST appends {query, verdict, grounding_label} and mints an UNSIGNED SHA-256 receipt chained to the prior entry (tamper-evident); GET recomputes the whole chain → CHAIN-INTACT/CHAIN-BROKEN (never softened), ephemeral in-memory ledger labelled honestly, MODELED, receipt-on-write-not-on-read", "owner": "WaveT-Dev1"},
|
|
@@ -366,7 +366,11 @@ def _local_generate(prompt: str, max_tokens: int = 256) -> dict:
|
|
| 366 |
{"role": "user", "content": prompt}]
|
| 367 |
out = llm.create_chat_completion(messages=msgs, max_tokens=max_tokens, temperature=0.2)
|
| 368 |
text = (out.get("choices") or [{}])[0].get("message", {}).get("content", "")
|
| 369 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
"tower_side": False, "latency_ms": int((time.time() - t0) * 1000),
|
| 371 |
"gguf_sha256_fp": _gguf_sha(_gguf_path())}
|
| 372 |
except Exception as e:
|
|
@@ -617,6 +621,24 @@ def alloy_governed_suggest(prompt: str, task_hint: str = "code", lam: float = 0.
|
|
| 617 |
"doctrine": DOCTRINE, "lambda_status": LAMBDA_STATUS,
|
| 618 |
"ts": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
|
| 619 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 620 |
if do_consensus:
|
| 621 |
# Honest demo consensus over production-eligible models' routing scores
|
| 622 |
# (answer_key is a coarse bucket of the routed score — a real, deterministic
|
|
@@ -666,7 +688,7 @@ def unify_into_registry() -> dict:
|
|
| 666 |
"tier": 90, # alloy band sits outside the legacy 0-5 closed tiers
|
| 667 |
"operator_mirrored": False,
|
| 668 |
"ecosystem_mirror": ["killinchu"],
|
| 669 |
-
"honest_stub":
|
| 670 |
"notes": "open-weight alloy; " + m.get("serving", ""),
|
| 671 |
})
|
| 672 |
report["added"].append(m["model_id"])
|
|
@@ -736,15 +758,49 @@ def register(app, ns: str = "a11oy", sign_fn=None) -> dict:
|
|
| 736 |
|
| 737 |
async def _health(request):
|
| 738 |
path = _gguf_path()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 739 |
return JSONResponse({
|
| 740 |
-
"backend": "llama.cpp", "backend_available":
|
| 741 |
"gguf_present": bool(path), "gguf_path": path,
|
| 742 |
"gguf_sha256_fp": _gguf_sha(path), "backend_error": _LLAMA_ERR,
|
| 743 |
-
"live_demo_possible":
|
| 744 |
-
"
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 748 |
"doctrine": DOCTRINE,
|
| 749 |
})
|
| 750 |
|
|
|
|
| 366 |
{"role": "user", "content": prompt}]
|
| 367 |
out = llm.create_chat_completion(messages=msgs, max_tokens=max_tokens, temperature=0.2)
|
| 368 |
text = (out.get("choices") or [{}])[0].get("message", {}).get("content", "")
|
| 369 |
+
if not isinstance(text, str) or not text.strip():
|
| 370 |
+
return {"served_locally": False, "text": None,
|
| 371 |
+
"honest_label": "llama.cpp returned an empty response",
|
| 372 |
+
"backend": "llama.cpp", "tower_side": True}
|
| 373 |
+
return {"served_locally": True, "text": text.strip(), "backend": "llama.cpp",
|
| 374 |
"tower_side": False, "latency_ms": int((time.time() - t0) * 1000),
|
| 375 |
"gguf_sha256_fp": _gguf_sha(_gguf_path())}
|
| 376 |
except Exception as e:
|
|
|
|
| 621 |
"doctrine": DOCTRINE, "lambda_status": LAMBDA_STATUS,
|
| 622 |
"ts": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
|
| 623 |
}
|
| 624 |
+
generation_receipt = {"ok": False, "inference_receipted": False,
|
| 625 |
+
"reason": "no successful local generation to receipt"}
|
| 626 |
+
if out["served_locally"] and gen.get("text"):
|
| 627 |
+
try:
|
| 628 |
+
import szl_governed_infer as _gi
|
| 629 |
+
generation_receipt = _gi.record_provider_generation(
|
| 630 |
+
prompt, gen["text"], chosen["model_id"],
|
| 631 |
+
tokens=0, base_url="llama.cpp://local")
|
| 632 |
+
except Exception as exc:
|
| 633 |
+
generation_receipt = {
|
| 634 |
+
"ok": False, "inference_receipted": False,
|
| 635 |
+
"reason": "durable receipt unavailable: %s" % type(exc).__name__}
|
| 636 |
+
out["generation_receipt"] = generation_receipt
|
| 637 |
+
out["inference_receipted"] = bool(
|
| 638 |
+
generation_receipt.get("inference_receipted"))
|
| 639 |
+
out["operational"] = bool(out["served_locally"]
|
| 640 |
+
and out["inference_receipted"])
|
| 641 |
+
out["honest_stub"] = not out["operational"]
|
| 642 |
if do_consensus:
|
| 643 |
# Honest demo consensus over production-eligible models' routing scores
|
| 644 |
# (answer_key is a coarse bucket of the routed score — a real, deterministic
|
|
|
|
| 688 |
"tier": 90, # alloy band sits outside the legacy 0-5 closed tiers
|
| 689 |
"operator_mirrored": False,
|
| 690 |
"ecosystem_mirror": ["killinchu"],
|
| 691 |
+
"honest_stub": True,
|
| 692 |
"notes": "open-weight alloy; " + m.get("serving", ""),
|
| 693 |
})
|
| 694 |
report["added"].append(m["model_id"])
|
|
|
|
| 758 |
|
| 759 |
async def _health(request):
|
| 760 |
path = _gguf_path()
|
| 761 |
+
backend_live = backend_available()
|
| 762 |
+
receipt_state = {"inference_receipted": False,
|
| 763 |
+
"successful_receipt_count": 0,
|
| 764 |
+
"chain_ok": True,
|
| 765 |
+
"latest_receipt_hash": None}
|
| 766 |
+
if backend_live:
|
| 767 |
+
try:
|
| 768 |
+
import szl_governed_infer as _gi
|
| 769 |
+
demo_statuses = [
|
| 770 |
+
_gi.inference_receipt_status(m["model_id"])
|
| 771 |
+
for m in ALLOY_ROSTER if m.get("tier_band") == "demo_cpu"
|
| 772 |
+
]
|
| 773 |
+
proven = [s for s in demo_statuses
|
| 774 |
+
if s.get("inference_receipted")]
|
| 775 |
+
receipt_state = (proven[-1] if proven else {
|
| 776 |
+
"inference_receipted": False,
|
| 777 |
+
"successful_receipt_count": 0,
|
| 778 |
+
"chain_ok": all(s.get("chain_ok", False)
|
| 779 |
+
for s in demo_statuses),
|
| 780 |
+
"latest_receipt_hash": None,
|
| 781 |
+
})
|
| 782 |
+
except Exception as exc:
|
| 783 |
+
receipt_state["chain_ok"] = False
|
| 784 |
+
receipt_state["reason"] = (
|
| 785 |
+
"receipt ledger unavailable: %s" % type(exc).__name__)
|
| 786 |
+
operational = bool(backend_live
|
| 787 |
+
and receipt_state.get("inference_receipted"))
|
| 788 |
return JSONResponse({
|
| 789 |
+
"backend": "llama.cpp", "backend_available": backend_live,
|
| 790 |
"gguf_present": bool(path), "gguf_path": path,
|
| 791 |
"gguf_sha256_fp": _gguf_sha(path), "backend_error": _LLAMA_ERR,
|
| 792 |
+
"live_demo_possible": backend_live,
|
| 793 |
+
"inference_receipted": bool(receipt_state.get("inference_receipted")),
|
| 794 |
+
"operational": operational,
|
| 795 |
+
"honest_stub": not operational,
|
| 796 |
+
"receipt_state": receipt_state,
|
| 797 |
+
"honest_label": ("LIVE_RECEIPTED: local CPU serving has durable inference proof."
|
| 798 |
+
if operational else
|
| 799 |
+
("REACHABLE_UNRECEIPTED: llama.cpp + GGUF load, but no "
|
| 800 |
+
"durable successful-inference receipt exists yet."
|
| 801 |
+
if backend_live else
|
| 802 |
+
"No local GGUF in this CPU Space -> capable tier is tower-side (honest). "
|
| 803 |
+
"Mount /app/models/*.gguf or set A11OY_ALLOY_GGUF to serve the demo tier live.")),
|
| 804 |
"doctrine": DOCTRINE,
|
| 805 |
})
|
| 806 |
|
|
@@ -953,6 +953,16 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 953 |
return HTMLResponse(_page_body(ns))
|
| 954 |
paths.append("/body-3d")
|
| 955 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 956 |
# ---- live JSON endpoints (wired to real evaluators + Khipu DAG + DSSE) ----
|
| 957 |
@app.post(f"{base}/yuyay-13/vote")
|
| 958 |
async def _e_yuyay(req: Request): # noqa
|
|
|
|
| 953 |
return HTMLResponse(_page_body(ns))
|
| 954 |
paths.append("/body-3d")
|
| 955 |
|
| 956 |
+
# Incremental Anatomy v6 keeps the v5 body route untouched and opens the
|
| 957 |
+
# receipt-driven cortical surface in the shared sovereign Three.js shell.
|
| 958 |
+
# That surface renders no node, edge, or pulse without a measured inventory
|
| 959 |
+
# decision / written feed receipt from the Brain reranker API.
|
| 960 |
+
@app.get("/body-3d-v6")
|
| 961 |
+
async def _p_body_v6(): # noqa
|
| 962 |
+
from starlette.responses import RedirectResponse
|
| 963 |
+
return RedirectResponse("/holographic#brainreranker", status_code=307)
|
| 964 |
+
paths.append("/body-3d-v6")
|
| 965 |
+
|
| 966 |
# ---- live JSON endpoints (wired to real evaluators + Khipu DAG + DSSE) ----
|
| 967 |
@app.post(f"{base}/yuyay-13/vote")
|
| 968 |
async def _e_yuyay(req: Request): # noqa
|
|
@@ -815,6 +815,23 @@ def salience_topk(k: int = 8, ns: str = "a11oy") -> list:
|
|
| 815 |
return view.get("source_salience", [])[:k]
|
| 816 |
|
| 817 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 818 |
# --------------------------------------------------------------------------- #
|
| 819 |
# Registration — POST /anatomy/pulse (write), GET /anatomy/salience (read).
|
| 820 |
# Raw-Request handlers via app.router.add_route (fallback add_api_route). These
|
|
@@ -851,10 +868,17 @@ def register(app, ns: str = "a11oy") -> list:
|
|
| 851 |
from starlette.responses import JSONResponse
|
| 852 |
return JSONResponse(self_audit(ns=ns))
|
| 853 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 854 |
routes = [
|
| 855 |
(f"{base}/pulse", _pulse_handler, ["POST"]),
|
| 856 |
(f"{base}/salience", _salience_handler, ["GET"]),
|
| 857 |
(f"{base}/self-audit", _audit_handler, ["GET"]),
|
|
|
|
| 858 |
]
|
| 859 |
router = getattr(app, "router", None)
|
| 860 |
add_route = getattr(router, "add_route", None) if router else None
|
|
|
|
| 815 |
return view.get("source_salience", [])[:k]
|
| 816 |
|
| 817 |
|
| 818 |
+
def evidence_receipt_anatomy(node_id: str, ns: str = "a11oy") -> tuple:
|
| 819 |
+
"""Existing Anatomy v5 bridge to the Brain evidence receipt contract.
|
| 820 |
+
|
| 821 |
+
This is a pure GET view: it reuses the reranker's deterministic per-node
|
| 822 |
+
anatomy and an already-written Ouroboros receipt when one matches the current
|
| 823 |
+
inventory. It never mints on read and returns explicit UNKNOWN/UNVERIFIED
|
| 824 |
+
fields when no written receipt exists.
|
| 825 |
+
"""
|
| 826 |
+
try:
|
| 827 |
+
import szl_brain_reranker as _reranker
|
| 828 |
+
return _reranker.anatomy_receipt(str(node_id), ns)
|
| 829 |
+
except Exception as exc:
|
| 830 |
+
return ({"ok": False, "status": LABEL_UNAVAILABLE,
|
| 831 |
+
"reason": f"evidence receipt unavailable: {type(exc).__name__}",
|
| 832 |
+
"receipt_sha256": "UNKNOWN"}, 503)
|
| 833 |
+
|
| 834 |
+
|
| 835 |
# --------------------------------------------------------------------------- #
|
| 836 |
# Registration — POST /anatomy/pulse (write), GET /anatomy/salience (read).
|
| 837 |
# Raw-Request handlers via app.router.add_route (fallback add_api_route). These
|
|
|
|
| 868 |
from starlette.responses import JSONResponse
|
| 869 |
return JSONResponse(self_audit(ns=ns))
|
| 870 |
|
| 871 |
+
async def _evidence_receipt_handler(request: fastapi.Request):
|
| 872 |
+
from starlette.responses import JSONResponse
|
| 873 |
+
node_id = str(request.path_params.get("node_id") or "")
|
| 874 |
+
body, status = evidence_receipt_anatomy(node_id, ns)
|
| 875 |
+
return JSONResponse(body, status_code=status)
|
| 876 |
+
|
| 877 |
routes = [
|
| 878 |
(f"{base}/pulse", _pulse_handler, ["POST"]),
|
| 879 |
(f"{base}/salience", _salience_handler, ["GET"]),
|
| 880 |
(f"{base}/self-audit", _audit_handler, ["GET"]),
|
| 881 |
+
(f"{base}/evidence-receipt/{{node_id:path}}", _evidence_receipt_handler, ["GET"]),
|
| 882 |
]
|
| 883 |
router = getattr(app, "router", None)
|
| 884 |
add_route = getattr(router, "add_route", None) if router else None
|
|
@@ -143,6 +143,12 @@ _REGISTRY = [
|
|
| 143 |
"Key identifier surfaced in verify receipts (non-secret).",
|
| 144 |
default=None),
|
| 145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
# ---- energy / GPU lungs (SECRET token + VARIABLE addressing/flags) ----
|
| 147 |
EnvSpec("A11OY_GPU_TOKEN", SECRET, "energy",
|
| 148 |
"Bearer token for the sovereign GPU node(s). Absent => joules are "
|
|
|
|
| 143 |
"Key identifier surfaced in verify receipts (non-secret).",
|
| 144 |
default=None),
|
| 145 |
|
| 146 |
+
# ---- governed compute authority (store only the bearer SHA-256) ----
|
| 147 |
+
EnvSpec("A11OY_COMPUTE_TOKEN_SHA256", SECRET, "compute",
|
| 148 |
+
"SHA-256 of the bearer accepted by stateful Yupaq compute routes. "
|
| 149 |
+
"Absent => submit/readback routes fail closed.",
|
| 150 |
+
required=False, default=None),
|
| 151 |
+
|
| 152 |
# ---- energy / GPU lungs (SECRET token + VARIABLE addressing/flags) ----
|
| 153 |
EnvSpec("A11OY_GPU_TOKEN", SECRET, "energy",
|
| 154 |
"Bearer token for the sovereign GPU node(s). Absent => joules are "
|
|
@@ -50,6 +50,7 @@ import json
|
|
| 50 |
import math
|
| 51 |
import os
|
| 52 |
import re
|
|
|
|
| 53 |
import urllib.error
|
| 54 |
import urllib.request
|
| 55 |
|
|
@@ -551,6 +552,9 @@ class BrainIndex:
|
|
| 551 |
Returns a REAL grounding subgraph regardless. Generated prose is ONLY
|
| 552 |
produced if a sovereign model is reachable; otherwise it is honestly
|
| 553 |
UNAVAILABLE — never fabricated."""
|
|
|
|
|
|
|
|
|
|
| 554 |
seeds = self.search(q, k=max(5, k))
|
| 555 |
seed_ids = [s["id"] for s in seeds]
|
| 556 |
personalization = None
|
|
@@ -577,9 +581,21 @@ class BrainIndex:
|
|
| 577 |
if c in self.community_summaries]
|
| 578 |
|
| 579 |
answer, answer_label, model = self._maybe_generate(q, grounding, global_ctx)
|
|
|
|
| 580 |
return {
|
| 581 |
"label": LBL_MODELED,
|
| 582 |
"query": q,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 583 |
"retrieval": "hippoRAG-PPR(local) ⊕ graphRAG-community(global), "
|
| 584 |
"LightRAG-mix merge",
|
| 585 |
"seeds": seeds,
|
|
@@ -652,11 +668,19 @@ class BrainIndex:
|
|
| 652 |
}
|
| 653 |
|
| 654 |
def index_status(self) -> dict:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 655 |
return {
|
| 656 |
"label": LBL_MODELED,
|
| 657 |
"content_hash": self.content_hash,
|
| 658 |
-
"
|
| 659 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 660 |
"embed_source": self.embed_source,
|
| 661 |
"embed_tier": self.embed_tier,
|
| 662 |
"embed_dim": self.embed_dim,
|
|
@@ -673,7 +697,8 @@ class BrainIndex:
|
|
| 673 |
"ollama_embeddings": self.embed_source.startswith("ollama"),
|
| 674 |
},
|
| 675 |
"note": ("hash-embedding similarity is MODELED (a deterministic "
|
| 676 |
-
"token-overlap proxy), NEVER MEASURED."
|
|
|
|
| 677 |
}
|
| 678 |
|
| 679 |
|
|
@@ -783,6 +808,10 @@ def _selftest() -> None:
|
|
| 783 |
|
| 784 |
st = idx.index_status()
|
| 785 |
assert st["embed_tier"] == LBL_MODELED, "embeddings are MODELED, never MEASURED"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 786 |
assert st["vector_backend"] in (
|
| 787 |
"sqlite-vec", "numpy-cosine", "python-cosine"), st["vector_backend"]
|
| 788 |
assert st["community_count"] >= 1, "at least one community"
|
|
@@ -820,6 +849,9 @@ def _selftest() -> None:
|
|
| 820 |
a = idx.ask("what proves the estate thesis", k=8)
|
| 821 |
assert a["grounding_subgraph"]["node_count"] >= 1, "real grounding subgraph"
|
| 822 |
assert a["cited_node_ids"], "cited node ids present"
|
|
|
|
|
|
|
|
|
|
| 823 |
if a["answer_model"] is None:
|
| 824 |
assert a["answer"] is None and a["answer_label"] == LBL_UNAVAILABLE, \
|
| 825 |
"no model => UNAVAILABLE, never a fabricated answer"
|
|
|
|
| 50 |
import math
|
| 51 |
import os
|
| 52 |
import re
|
| 53 |
+
import time
|
| 54 |
import urllib.error
|
| 55 |
import urllib.request
|
| 56 |
|
|
|
|
| 552 |
Returns a REAL grounding subgraph regardless. Generated prose is ONLY
|
| 553 |
produced if a sovereign model is reachable; otherwise it is honestly
|
| 554 |
UNAVAILABLE — never fabricated."""
|
| 555 |
+
# Monotonic server timing only. This measures elapsed work in this
|
| 556 |
+
# process; it is not a browser, transport, or end-to-end latency claim.
|
| 557 |
+
started_ns = time.perf_counter_ns()
|
| 558 |
seeds = self.search(q, k=max(5, k))
|
| 559 |
seed_ids = [s["id"] for s in seeds]
|
| 560 |
personalization = None
|
|
|
|
| 581 |
if c in self.community_summaries]
|
| 582 |
|
| 583 |
answer, answer_label, model = self._maybe_generate(q, grounding, global_ctx)
|
| 584 |
+
elapsed_ms = round((time.perf_counter_ns() - started_ns) / 1_000_000, 3)
|
| 585 |
return {
|
| 586 |
"label": LBL_MODELED,
|
| 587 |
"query": q,
|
| 588 |
+
"query_latency": {
|
| 589 |
+
"label": "MEASURED",
|
| 590 |
+
"value_ms": elapsed_ms,
|
| 591 |
+
"unit": "milliseconds",
|
| 592 |
+
"clock": "time.perf_counter_ns (monotonic)",
|
| 593 |
+
"basis": "server-observed elapsed duration for this request",
|
| 594 |
+
"scope": ("BrainIndex.ask retrieval, graph expansion, community context, "
|
| 595 |
+
"and optional sovereign generation"),
|
| 596 |
+
"excludes": ("response serialization, network transport, and browser "
|
| 597 |
+
"render time"),
|
| 598 |
+
},
|
| 599 |
"retrieval": "hippoRAG-PPR(local) ⊕ graphRAG-community(global), "
|
| 600 |
"LightRAG-mix merge",
|
| 601 |
"seeds": seeds,
|
|
|
|
| 668 |
}
|
| 669 |
|
| 670 |
def index_status(self) -> dict:
|
| 671 |
+
# Raw graph facts are exposed together so clients cannot accidentally
|
| 672 |
+
# conflate people, distinct artifacts, dedupe lineage, or admission.
|
| 673 |
+
raw_node_count = self.graph.get("node_count", len(self.nodes))
|
| 674 |
+
raw_link_count = self.graph.get("link_count", len(self.links))
|
| 675 |
return {
|
| 676 |
"label": LBL_MODELED,
|
| 677 |
"content_hash": self.content_hash,
|
| 678 |
+
"raw_node_count": raw_node_count,
|
| 679 |
+
"node_count": raw_node_count,
|
| 680 |
+
"link_count": raw_link_count,
|
| 681 |
+
"distinct_artifacts": self.graph.get("distinct_artifacts"),
|
| 682 |
+
"person_node_count": self.graph.get("person_node_count"),
|
| 683 |
+
"artifact_note": self.graph.get("artifact_note"),
|
| 684 |
"embed_source": self.embed_source,
|
| 685 |
"embed_tier": self.embed_tier,
|
| 686 |
"embed_dim": self.embed_dim,
|
|
|
|
| 697 |
"ollama_embeddings": self.embed_source.startswith("ollama"),
|
| 698 |
},
|
| 699 |
"note": ("hash-embedding similarity is MODELED (a deterministic "
|
| 700 |
+
"token-overlap proxy), NEVER MEASURED. Graph counts come "
|
| 701 |
+
"from the current graph and do not imply training admission."),
|
| 702 |
}
|
| 703 |
|
| 704 |
|
|
|
|
| 808 |
|
| 809 |
st = idx.index_status()
|
| 810 |
assert st["embed_tier"] == LBL_MODELED, "embeddings are MODELED, never MEASURED"
|
| 811 |
+
assert st["raw_node_count"] == idx.graph["node_count"]
|
| 812 |
+
assert st["link_count"] == idx.graph["link_count"]
|
| 813 |
+
assert st["distinct_artifacts"] == idx.graph.get("distinct_artifacts")
|
| 814 |
+
assert st["person_node_count"] == idx.graph.get("person_node_count")
|
| 815 |
assert st["vector_backend"] in (
|
| 816 |
"sqlite-vec", "numpy-cosine", "python-cosine"), st["vector_backend"]
|
| 817 |
assert st["community_count"] >= 1, "at least one community"
|
|
|
|
| 849 |
a = idx.ask("what proves the estate thesis", k=8)
|
| 850 |
assert a["grounding_subgraph"]["node_count"] >= 1, "real grounding subgraph"
|
| 851 |
assert a["cited_node_ids"], "cited node ids present"
|
| 852 |
+
assert a["query_latency"]["label"] == "MEASURED"
|
| 853 |
+
assert "perf_counter_ns" in a["query_latency"]["clock"]
|
| 854 |
+
assert "browser" in a["query_latency"]["excludes"]
|
| 855 |
if a["answer_model"] is None:
|
| 856 |
assert a["answer"] is None and a["answer_label"] == LBL_UNAVAILABLE, \
|
| 857 |
"no model => UNAVAILABLE, never a fabricated answer"
|
|
@@ -0,0 +1,978 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Fail-closed Brain evidence inventory, reranker proposal data, and local feed.
|
| 3 |
+
|
| 4 |
+
This service does not scrape, train, or promote a model. It turns the Brain graph and
|
| 5 |
+
the canonical local corpus manifests into auditable *proposal* data. Every raw graph
|
| 6 |
+
node receives a deterministic inventory decision. Reranker rows are admitted only
|
| 7 |
+
when their evidence is an exact projection of a real Brain node and all declared
|
| 8 |
+
source hashes match verified local bytes.
|
| 9 |
+
|
| 10 |
+
GETs are pure reads. The two POST paths are loopback-only writes:
|
| 11 |
+
|
| 12 |
+
* ``rows`` appends one validated, hash-linked local row;
|
| 13 |
+
* ``feed/refresh`` checkpoints one bounded local Ouroboros cycle.
|
| 14 |
+
|
| 15 |
+
Missing canonical manifests always produce ``BLOCKED`` dataset/model/evaluation
|
| 16 |
+
readiness and zero rows. No threshold or proof status is upgraded.
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import datetime
|
| 20 |
+
import hashlib
|
| 21 |
+
import ipaddress
|
| 22 |
+
import json
|
| 23 |
+
import math
|
| 24 |
+
import os
|
| 25 |
+
import pathlib
|
| 26 |
+
import re
|
| 27 |
+
import tempfile
|
| 28 |
+
import threading
|
| 29 |
+
import time
|
| 30 |
+
from typing import Any, Mapping
|
| 31 |
+
|
| 32 |
+
import szl_braincorpus as _corpus_admission
|
| 33 |
+
import szl_brain_corpus as _brain_projection
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
SERVICE_SCHEMA = "szl.brain.reranker-readiness.v1"
|
| 37 |
+
SOURCE_SCHEMA = "szl.brain.reranker-source.v1"
|
| 38 |
+
ROW_SCHEMA = "szl.brain.reranker-row.v1"
|
| 39 |
+
LEDGER_SCHEMA = "szl.brain.reranker-ledger.v1"
|
| 40 |
+
FEED_SCHEMA = "szl.brain.ouroboros-feed.v1"
|
| 41 |
+
MODEL_SCHEMA = "szl.brain.reranker-model.v1"
|
| 42 |
+
EVAL_SCHEMA = "szl.brain.reranker-evaluation.v1"
|
| 43 |
+
|
| 44 |
+
READY = "READY"
|
| 45 |
+
BLOCKED = "BLOCKED"
|
| 46 |
+
DEGRADED = "DEGRADED"
|
| 47 |
+
UNAVAILABLE = "UNAVAILABLE"
|
| 48 |
+
UNKNOWN = "UNKNOWN"
|
| 49 |
+
UNVERIFIED = "UNVERIFIED"
|
| 50 |
+
|
| 51 |
+
EXAMPLE_TYPES = ("positive", "negative", "abstention", "refutation")
|
| 52 |
+
TARGETS = {"positive": 1.0, "negative": 0.0, "abstention": 0.0, "refutation": 0.0}
|
| 53 |
+
FEED_STAGES = (
|
| 54 |
+
"DISCOVER", "FETCH", "HASH", "CLASSIFY", "DEDUP", "VERIFY",
|
| 55 |
+
"ADMIT_OR_QUARANTINE", "EVALUATE", "RECEIPT", "REFRESH",
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
MAX_QUERY_CHARS = 1_024
|
| 59 |
+
MAX_EVIDENCE_CHARS = 12_000
|
| 60 |
+
MAX_ENTITY_CHARS = 160
|
| 61 |
+
MAX_ARTIFACT_EXAMPLES = 10_000
|
| 62 |
+
MAX_LOCAL_ROWS = 2_000
|
| 63 |
+
MAX_LEDGER_BYTES = 32 * 1024 * 1024
|
| 64 |
+
MAX_INVENTORY_PAGE = 500
|
| 65 |
+
MAX_DATASET_PAGE = 500
|
| 66 |
+
FEED_MIN_INTERVAL_S = 60
|
| 67 |
+
FEED_MAX_BACKOFF_S = 3_600
|
| 68 |
+
FEED_NODE_BUDGET = 20_000
|
| 69 |
+
FEED_SOURCE_BUDGET = 5_000
|
| 70 |
+
|
| 71 |
+
_SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
|
| 72 |
+
_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,159}$")
|
| 73 |
+
_LOCK = threading.RLock()
|
| 74 |
+
_INVENTORY_CACHE: dict[str, Any] = {"key": None, "value": None}
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def _now() -> str:
|
| 78 |
+
return datetime.datetime.now(datetime.timezone.utc).isoformat()
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def _canonical_bytes(value: Any) -> bytes:
|
| 82 |
+
return json.dumps(value, sort_keys=True, separators=(",", ":"),
|
| 83 |
+
ensure_ascii=False).encode("utf-8")
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def _sha(value: Any) -> str:
|
| 87 |
+
return hashlib.sha256(_canonical_bytes(value)).hexdigest()
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _sha_text(value: Any) -> str:
|
| 91 |
+
return hashlib.sha256(str(value).encode("utf-8")).hexdigest()
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def _is_sha(value: Any) -> bool:
|
| 95 |
+
return bool(_SHA256_RE.fullmatch(str(value or "").lower()))
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def _repo_root(repo_root: pathlib.Path | str | None = None) -> pathlib.Path:
|
| 99 |
+
return pathlib.Path(repo_root or pathlib.Path(__file__).resolve().parent).resolve()
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def _runtime_path(name: str, environ: Mapping[str, str], explicit: str) -> pathlib.Path:
|
| 103 |
+
configured = str(environ.get(explicit, "")).strip()
|
| 104 |
+
if configured:
|
| 105 |
+
return pathlib.Path(configured).expanduser().resolve()
|
| 106 |
+
state_dir = str(environ.get("A11OY_RUNTIME_STATE_DIR", "")).strip()
|
| 107 |
+
base = pathlib.Path(state_dir).expanduser().resolve() if state_dir else (
|
| 108 |
+
pathlib.Path(tempfile.gettempdir()) / "a11oy-brain-reranker"
|
| 109 |
+
).resolve()
|
| 110 |
+
return base / name
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def _ledger_path(environ: Mapping[str, str]) -> pathlib.Path:
|
| 114 |
+
return _runtime_path("validated-rows.jsonl", environ,
|
| 115 |
+
"A11OY_BRAIN_RERANKER_LEDGER")
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def _feed_path(environ: Mapping[str, str]) -> pathlib.Path:
|
| 119 |
+
return _runtime_path("ouroboros-feed.jsonl", environ,
|
| 120 |
+
"A11OY_BRAIN_FEED_LEDGER")
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def _safe_read_json(path: pathlib.Path, maximum: int) -> tuple[Any | None, str | None]:
|
| 124 |
+
try:
|
| 125 |
+
with path.open("rb") as handle:
|
| 126 |
+
raw = handle.read(maximum + 1)
|
| 127 |
+
if len(raw) > maximum:
|
| 128 |
+
return None, f"FILE_TOO_LARGE:{len(raw)}>{maximum}"
|
| 129 |
+
return json.loads(raw.decode("utf-8")), None
|
| 130 |
+
except FileNotFoundError:
|
| 131 |
+
return None, "FILE_NOT_FOUND"
|
| 132 |
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
| 133 |
+
return None, f"READ_FAILED:{type(exc).__name__}"
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def _source_family(node: Mapping[str, Any]) -> str:
|
| 137 |
+
raw = str(node.get("url") or node.get("source") or node.get("path") or
|
| 138 |
+
node.get("derived_from") or "").strip()
|
| 139 |
+
if raw.startswith(("http://", "https://")):
|
| 140 |
+
try:
|
| 141 |
+
from urllib.parse import urlsplit
|
| 142 |
+
return (urlsplit(raw).hostname or UNKNOWN).lower()
|
| 143 |
+
except Exception:
|
| 144 |
+
return UNKNOWN
|
| 145 |
+
if raw:
|
| 146 |
+
return raw.replace("\\", "/").split("/", 1)[0][:160]
|
| 147 |
+
return UNKNOWN
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def _source_url(node: Mapping[str, Any]) -> str:
|
| 151 |
+
raw = str(node.get("url") or "").strip()
|
| 152 |
+
return raw if raw.startswith(("http://", "https://")) else UNKNOWN
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def _revision(node: Mapping[str, Any]) -> str:
|
| 156 |
+
for key in ("revision", "commit", "commit_sha", "sha", "version", "rev"):
|
| 157 |
+
value = str(node.get(key) or "").strip()
|
| 158 |
+
if value:
|
| 159 |
+
return value[:200]
|
| 160 |
+
return UNKNOWN
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
def _license(node: Mapping[str, Any]) -> str:
|
| 164 |
+
for key in ("license", "license_id", "spdx", "spdx_id"):
|
| 165 |
+
value = str(node.get(key) or "").strip()
|
| 166 |
+
if value:
|
| 167 |
+
return value[:200]
|
| 168 |
+
return UNKNOWN
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
def _freshness(node: Mapping[str, Any]) -> tuple[str, str]:
|
| 172 |
+
for key in ("retrieved_at", "captured_at", "updated_at", "published_at", "timestamp", "date"):
|
| 173 |
+
value = str(node.get(key) or "").strip()
|
| 174 |
+
if value:
|
| 175 |
+
return value[:200], "SOURCE_TIMESTAMP"
|
| 176 |
+
return UNKNOWN, "UNVERIFIED"
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def _node_content(node: Mapping[str, Any]) -> dict[str, Any]:
|
| 180 |
+
"""Hash only source-authored graph fields; never request time or derived verdicts."""
|
| 181 |
+
return {str(k): node[k] for k in sorted(node) if not str(k).startswith("_")}
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def _canonical_key(node: Mapping[str, Any], content_sha256: str) -> str:
|
| 185 |
+
url = _source_url(node)
|
| 186 |
+
if url != UNKNOWN:
|
| 187 |
+
return "url:" + url.rstrip("/").lower()
|
| 188 |
+
formula = str(node.get("formula_id") or "").strip().upper()
|
| 189 |
+
if formula:
|
| 190 |
+
return "formula:" + formula
|
| 191 |
+
title = str(node.get("title") or node.get("label") or "").strip().lower()
|
| 192 |
+
kind = str(node.get("kind") or "node").strip().lower()
|
| 193 |
+
if title:
|
| 194 |
+
return f"{kind}:{title}"
|
| 195 |
+
return "content:" + content_sha256
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
def _graph_nodes(ns: str = "a11oy") -> tuple[list[dict[str, Any]], str | None]:
|
| 199 |
+
try:
|
| 200 |
+
import a11oy_brain_graph as graph
|
| 201 |
+
built = graph.get_brain_graph(ns)
|
| 202 |
+
nodes = built.get("nodes") if isinstance(built, dict) else None
|
| 203 |
+
if not isinstance(nodes, list):
|
| 204 |
+
return [], "GRAPH_NODES_UNAVAILABLE"
|
| 205 |
+
return [dict(n) for n in nodes if isinstance(n, dict)], None
|
| 206 |
+
except Exception as exc:
|
| 207 |
+
return [], f"GRAPH_UNAVAILABLE:{type(exc).__name__}"
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
def _canonical_context(repo_root: pathlib.Path | str | None,
|
| 211 |
+
environ: Mapping[str, str]) -> dict[str, Any]:
|
| 212 |
+
root = _repo_root(repo_root)
|
| 213 |
+
status = _corpus_admission.build_corpus_status(root, environ)
|
| 214 |
+
sources = status.get("sources") if isinstance(status, dict) else []
|
| 215 |
+
source_map: dict[tuple[str, str], dict[str, Any]] = {}
|
| 216 |
+
complete = True
|
| 217 |
+
reasons: list[str] = []
|
| 218 |
+
for source in sources if isinstance(sources, list) else []:
|
| 219 |
+
source_type = str(source.get("source_type") or "")
|
| 220 |
+
source_status = str(source.get("status") or "")
|
| 221 |
+
manifest_hash = str(source.get("manifest_sha256") or "").lower()
|
| 222 |
+
if source_status not in {"INGESTED_LOCAL", "PARTIAL_QUARANTINE"} or not _is_sha(manifest_hash):
|
| 223 |
+
complete = False
|
| 224 |
+
reasons.append(f"{source_type}:{source_status or 'SOURCE_UNAVAILABLE'}")
|
| 225 |
+
manifest_path, boundary, origin, path_error = _corpus_admission._safe_manifest_path(
|
| 226 |
+
source_type, root, environ,
|
| 227 |
+
)
|
| 228 |
+
for entry in source.get("entries", []) if isinstance(source.get("entries"), list) else []:
|
| 229 |
+
if not entry.get("artifact_verified"):
|
| 230 |
+
continue
|
| 231 |
+
source_path = str(entry.get("source_path") or "")
|
| 232 |
+
artifact = (boundary / pathlib.Path(source_path)).resolve() if source_path else None
|
| 233 |
+
if artifact is None or not _corpus_admission._inside(artifact, boundary):
|
| 234 |
+
continue
|
| 235 |
+
source_map[(source_type, str(entry.get("id") or ""))] = {
|
| 236 |
+
"source_type": source_type,
|
| 237 |
+
"source_entry_id": str(entry.get("id") or ""),
|
| 238 |
+
"manifest_sha256": manifest_hash,
|
| 239 |
+
"manifest_path": manifest_path,
|
| 240 |
+
"manifest_origin": origin,
|
| 241 |
+
"artifact_path": artifact,
|
| 242 |
+
"artifact_sha256": str(entry.get("artifact_sha256") or "").lower(),
|
| 243 |
+
"artifact_receipt": entry.get("artifact_receipt"),
|
| 244 |
+
"proof_receipt": entry.get("proof_receipt"),
|
| 245 |
+
"evidence_class": entry.get("effective_class"),
|
| 246 |
+
}
|
| 247 |
+
if path_error:
|
| 248 |
+
complete = False
|
| 249 |
+
reasons.append(f"{source_type}:{path_error}")
|
| 250 |
+
if len(sources or []) != len(_corpus_admission.SOURCE_TYPES):
|
| 251 |
+
complete = False
|
| 252 |
+
reasons.append("CANONICAL_SOURCE_ROSTER_INCOMPLETE")
|
| 253 |
+
return {
|
| 254 |
+
"complete": complete,
|
| 255 |
+
"reasons": sorted(set(reasons)),
|
| 256 |
+
"status": status,
|
| 257 |
+
"source_map": source_map,
|
| 258 |
+
"root": root,
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def _brain_docs(ns: str) -> tuple[dict[str, dict[str, str]], str | None]:
|
| 263 |
+
try:
|
| 264 |
+
docs = _brain_projection.corpus(ns, limit=20_000, include_people=True)
|
| 265 |
+
except Exception as exc:
|
| 266 |
+
return {}, f"BRAIN_PROJECTION_FAILED:{type(exc).__name__}"
|
| 267 |
+
result: dict[str, dict[str, str]] = {}
|
| 268 |
+
for doc in docs if isinstance(docs, list) else []:
|
| 269 |
+
if isinstance(doc, dict) and doc.get("id"):
|
| 270 |
+
result[str(doc["id"])] = {
|
| 271 |
+
"id": str(doc["id"]), "text": str(doc.get("text") or ""),
|
| 272 |
+
"source": str(doc.get("source") or ""),
|
| 273 |
+
}
|
| 274 |
+
return result, None if result else "BRAIN_PROJECTION_EMPTY"
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
def build_inventory(ns: str = "a11oy", repo_root: pathlib.Path | str | None = None,
|
| 278 |
+
environ: Mapping[str, str] | None = None) -> dict[str, Any]:
|
| 279 |
+
"""Return one decision for every raw graph node, plus canonical/dedupe posture."""
|
| 280 |
+
env = os.environ if environ is None else environ
|
| 281 |
+
canonical = _canonical_context(repo_root, env)
|
| 282 |
+
nodes, graph_error = _graph_nodes(ns)
|
| 283 |
+
graph_hash = _sha([_node_content(n) for n in nodes]) if nodes else None
|
| 284 |
+
cache_key = _sha({"graph": graph_hash, "canonical": [
|
| 285 |
+
(s.get("source_type"), s.get("manifest_sha256"), s.get("status"))
|
| 286 |
+
for s in (canonical["status"].get("sources") or [])
|
| 287 |
+
]})
|
| 288 |
+
with _LOCK:
|
| 289 |
+
if _INVENTORY_CACHE.get("key") == cache_key and _INVENTORY_CACHE.get("value") is not None:
|
| 290 |
+
return _INVENTORY_CACHE["value"]
|
| 291 |
+
|
| 292 |
+
seen: dict[str, str] = {}
|
| 293 |
+
decisions: list[dict[str, Any]] = []
|
| 294 |
+
reasons: dict[str, int] = {}
|
| 295 |
+
canonical_count = 0
|
| 296 |
+
for index, node in enumerate(nodes):
|
| 297 |
+
node_id = str(node.get("id") or f"raw-index:{index}")
|
| 298 |
+
content_sha = _sha(_node_content(node))
|
| 299 |
+
key = _canonical_key(node, content_sha)
|
| 300 |
+
duplicate_of = seen.get(key)
|
| 301 |
+
if duplicate_of is None:
|
| 302 |
+
seen[key] = node_id
|
| 303 |
+
canonical_count += 1
|
| 304 |
+
source_identity = str(node.get("source") or node.get("url") or node.get("path") or
|
| 305 |
+
node.get("derived_from") or UNKNOWN)[:500]
|
| 306 |
+
retrieved_at, freshness_basis = _freshness(node)
|
| 307 |
+
reason_codes: list[str] = []
|
| 308 |
+
if duplicate_of:
|
| 309 |
+
reason_codes.append("DUPLICATE_CANONICAL_KEY")
|
| 310 |
+
if source_identity == UNKNOWN:
|
| 311 |
+
reason_codes.append("PROVENANCE_UNKNOWN")
|
| 312 |
+
if _revision(node) == UNKNOWN:
|
| 313 |
+
reason_codes.append("REVISION_UNKNOWN")
|
| 314 |
+
if _license(node) == UNKNOWN:
|
| 315 |
+
reason_codes.append("LICENSE_UNKNOWN")
|
| 316 |
+
if retrieved_at == UNKNOWN:
|
| 317 |
+
reason_codes.append("FRESHNESS_UNKNOWN")
|
| 318 |
+
if not canonical["complete"]:
|
| 319 |
+
reason_codes.append("CANONICAL_MANIFESTS_REQUIRED")
|
| 320 |
+
decision = "ADMITTED_TO_CANONICAL_MAP" if not reason_codes else "QUARANTINED"
|
| 321 |
+
if decision == "QUARANTINED":
|
| 322 |
+
for reason in reason_codes:
|
| 323 |
+
reasons[reason] = reasons.get(reason, 0) + 1
|
| 324 |
+
anatomy_core = {
|
| 325 |
+
"raw_index": index,
|
| 326 |
+
"brain_node_id": node_id,
|
| 327 |
+
"node_content_sha256": content_sha,
|
| 328 |
+
"source_identity": source_identity,
|
| 329 |
+
"source_url": _source_url(node),
|
| 330 |
+
"source_family": _source_family(node),
|
| 331 |
+
"source_revision": _revision(node),
|
| 332 |
+
"license": _license(node),
|
| 333 |
+
"robots_policy": "NOT_APPLICABLE_LOCAL_SNAPSHOT",
|
| 334 |
+
"retrieved_at": retrieved_at,
|
| 335 |
+
"freshness_basis": freshness_basis,
|
| 336 |
+
"canonical_key_sha256": _sha_text(key),
|
| 337 |
+
"canonical_node_id": duplicate_of or node_id,
|
| 338 |
+
"deduplicated": bool(duplicate_of),
|
| 339 |
+
"formula_id": str(node.get("formula_id") or UNKNOWN),
|
| 340 |
+
"proof_status": str(node.get("proof_status") or UNKNOWN),
|
| 341 |
+
"admission_decision": decision,
|
| 342 |
+
"reason_codes": reason_codes,
|
| 343 |
+
"split_assignment": "NOT_ASSIGNED",
|
| 344 |
+
"training_eligible": False,
|
| 345 |
+
"model_receipt_sha256": UNKNOWN,
|
| 346 |
+
"evaluation_receipt_sha256": UNKNOWN,
|
| 347 |
+
}
|
| 348 |
+
decisions.append({**anatomy_core, "anatomy_record_sha256": _sha(anatomy_core)})
|
| 349 |
+
|
| 350 |
+
inventory_core = {
|
| 351 |
+
"graph_content_sha256": graph_hash,
|
| 352 |
+
"raw_node_count": len(nodes),
|
| 353 |
+
"decision_count": len(decisions),
|
| 354 |
+
"canonical_node_count": canonical_count,
|
| 355 |
+
"quarantined_node_count": sum(d["admission_decision"] == "QUARANTINED" for d in decisions),
|
| 356 |
+
"reason_counts": dict(sorted(reasons.items())),
|
| 357 |
+
}
|
| 358 |
+
value = {
|
| 359 |
+
"ok": graph_error is None,
|
| 360 |
+
"label": "MEASURED" if graph_error is None else UNAVAILABLE,
|
| 361 |
+
"schema_version": SERVICE_SCHEMA,
|
| 362 |
+
"inventory": inventory_core,
|
| 363 |
+
"inventory_sha256": _sha(inventory_core),
|
| 364 |
+
"canonical_manifests_complete": canonical["complete"],
|
| 365 |
+
"canonical_manifest_reasons": canonical["reasons"],
|
| 366 |
+
"decisions": decisions,
|
| 367 |
+
"graph_error": graph_error,
|
| 368 |
+
"note": "Every raw node has one decision; no node is silently dropped.",
|
| 369 |
+
}
|
| 370 |
+
with _LOCK:
|
| 371 |
+
_INVENTORY_CACHE.update({"key": cache_key, "value": value})
|
| 372 |
+
return value
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
def _row_core(example: Mapping[str, Any], source: Mapping[str, Any],
|
| 376 |
+
doc: Mapping[str, str], origin: str) -> tuple[dict[str, Any] | None, list[str]]:
|
| 377 |
+
errors: list[str] = []
|
| 378 |
+
example_type = str(example.get("example_type") or "").strip().lower()
|
| 379 |
+
query = str(example.get("query") or "").strip()
|
| 380 |
+
evidence = str(example.get("evidence_text") or "")
|
| 381 |
+
example_id = str(example.get("example_id") or "").strip()
|
| 382 |
+
entity_id = str(example.get("entity_id") or "").strip()
|
| 383 |
+
node_id = str(example.get("brain_node_id") or "").strip()
|
| 384 |
+
try:
|
| 385 |
+
target = float(example.get("target_relevance"))
|
| 386 |
+
except (TypeError, ValueError):
|
| 387 |
+
target = math.nan
|
| 388 |
+
if not _ID_RE.fullmatch(example_id): errors.append("INVALID_EXAMPLE_ID")
|
| 389 |
+
if not _ID_RE.fullmatch(entity_id): errors.append("INVALID_ENTITY_ID")
|
| 390 |
+
if not query or len(query) > MAX_QUERY_CHARS: errors.append("INVALID_QUERY")
|
| 391 |
+
if not evidence or len(evidence) > MAX_EVIDENCE_CHARS: errors.append("INVALID_EVIDENCE")
|
| 392 |
+
if example_type not in EXAMPLE_TYPES: errors.append("INVALID_EXAMPLE_TYPE")
|
| 393 |
+
if example_type in TARGETS and target != TARGETS[example_type]: errors.append("TARGET_TYPE_MISMATCH")
|
| 394 |
+
if node_id != doc.get("id"): errors.append("BRAIN_NODE_ID_MISMATCH")
|
| 395 |
+
if evidence != doc.get("text"): errors.append("EVIDENCE_NOT_EXACT_BRAIN_PROJECTION")
|
| 396 |
+
node_hash = _sha({"id": doc.get("id"), "text": doc.get("text"), "source": doc.get("source")})
|
| 397 |
+
source_hash = _sha_text(doc.get("source"))
|
| 398 |
+
declared_node_hash = str(example.get("brain_node_sha256") or "").lower()
|
| 399 |
+
declared_source_hash = str(example.get("brain_source_sha256") or "").lower()
|
| 400 |
+
if declared_node_hash != node_hash: errors.append("BRAIN_NODE_HASH_MISMATCH")
|
| 401 |
+
if declared_source_hash != source_hash: errors.append("BRAIN_SOURCE_HASH_MISMATCH")
|
| 402 |
+
if errors:
|
| 403 |
+
return None, sorted(set(errors))
|
| 404 |
+
source_receipt = (source.get("artifact_receipt") or {}).get("receipt_sha256")
|
| 405 |
+
if not _is_sha(source_receipt):
|
| 406 |
+
source_receipt = (source.get("proof_receipt") or {}).get("receipt_sha256")
|
| 407 |
+
if not _is_sha(source_receipt):
|
| 408 |
+
source_receipt = _sha({
|
| 409 |
+
"source_manifest_sha256": source["manifest_sha256"],
|
| 410 |
+
"source_artifact_sha256": source["artifact_sha256"],
|
| 411 |
+
"brain_node_sha256": node_hash,
|
| 412 |
+
"brain_source_sha256": source_hash,
|
| 413 |
+
})
|
| 414 |
+
core = {
|
| 415 |
+
"schema_version": ROW_SCHEMA,
|
| 416 |
+
"example_id": example_id,
|
| 417 |
+
"example_type": example_type,
|
| 418 |
+
"target_relevance": target,
|
| 419 |
+
"query": query,
|
| 420 |
+
"evidence_text": evidence,
|
| 421 |
+
"entity_id": entity_id,
|
| 422 |
+
"source_type": source["source_type"],
|
| 423 |
+
"source_entry_id": source["source_entry_id"],
|
| 424 |
+
"source_manifest_sha256": source["manifest_sha256"],
|
| 425 |
+
"source_artifact_sha256": source["artifact_sha256"],
|
| 426 |
+
"source_receipt_sha256": source_receipt,
|
| 427 |
+
"brain_node_id": node_id,
|
| 428 |
+
"brain_node_sha256": node_hash,
|
| 429 |
+
"brain_source_sha256": source_hash,
|
| 430 |
+
"origin": origin,
|
| 431 |
+
}
|
| 432 |
+
return {**core, "row_receipt_sha256": _sha(core)}, []
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
def _load_embedded_rows(canonical: Mapping[str, Any], docs: Mapping[str, dict[str, str]]) -> tuple[list[dict], list[dict]]:
|
| 436 |
+
rows: list[dict] = []
|
| 437 |
+
rejected: list[dict] = []
|
| 438 |
+
for source in canonical["source_map"].values():
|
| 439 |
+
payload, error = _safe_read_json(source["artifact_path"], _corpus_admission.MAX_ARTIFACT_BYTES)
|
| 440 |
+
if error or not isinstance(payload, dict) or payload.get("schema_version") != SOURCE_SCHEMA:
|
| 441 |
+
continue
|
| 442 |
+
examples = payload.get("examples")
|
| 443 |
+
if not isinstance(examples, list):
|
| 444 |
+
rejected.append({"source_entry_id": source["source_entry_id"],
|
| 445 |
+
"reasons": ["EXAMPLES_MUST_BE_ARRAY"]})
|
| 446 |
+
continue
|
| 447 |
+
for raw in examples[:MAX_ARTIFACT_EXAMPLES]:
|
| 448 |
+
if not isinstance(raw, dict):
|
| 449 |
+
rejected.append({"source_entry_id": source["source_entry_id"],
|
| 450 |
+
"reasons": ["EXAMPLE_NOT_OBJECT"]})
|
| 451 |
+
continue
|
| 452 |
+
doc = docs.get(str(raw.get("brain_node_id") or ""), {})
|
| 453 |
+
row, reasons = _row_core(raw, source, doc, "CANONICAL_ARTIFACT")
|
| 454 |
+
if row:
|
| 455 |
+
rows.append(row)
|
| 456 |
+
else:
|
| 457 |
+
rejected.append({"source_entry_id": source["source_entry_id"],
|
| 458 |
+
"example_id": raw.get("example_id"), "reasons": reasons})
|
| 459 |
+
return rows, rejected
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
def _read_jsonl(path: pathlib.Path, maximum: int) -> tuple[list[Any], list[str]]:
|
| 463 |
+
if not path.is_file():
|
| 464 |
+
return [], []
|
| 465 |
+
try:
|
| 466 |
+
if path.stat().st_size > maximum:
|
| 467 |
+
return [], [f"LEDGER_TOO_LARGE:{path.stat().st_size}>{maximum}"]
|
| 468 |
+
rows, errors = [], []
|
| 469 |
+
with path.open("r", encoding="utf-8") as handle:
|
| 470 |
+
for i, line in enumerate(handle):
|
| 471 |
+
try:
|
| 472 |
+
rows.append(json.loads(line))
|
| 473 |
+
except json.JSONDecodeError:
|
| 474 |
+
errors.append(f"INVALID_JSON_LINE:{i + 1}")
|
| 475 |
+
return rows, errors
|
| 476 |
+
except OSError as exc:
|
| 477 |
+
return [], [f"LEDGER_READ_FAILED:{type(exc).__name__}"]
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
def _load_local_rows(path: pathlib.Path, canonical: Mapping[str, Any],
|
| 481 |
+
docs: Mapping[str, dict[str, str]]) -> tuple[list[dict], dict[str, Any]]:
|
| 482 |
+
records, errors = _read_jsonl(path, MAX_LEDGER_BYTES)
|
| 483 |
+
rows: list[dict] = []
|
| 484 |
+
prev = "0" * 64
|
| 485 |
+
valid_chain = not errors
|
| 486 |
+
for i, record in enumerate(records[:MAX_LOCAL_ROWS]):
|
| 487 |
+
if not isinstance(record, dict) or record.get("schema_version") != LEDGER_SCHEMA:
|
| 488 |
+
errors.append(f"INVALID_LEDGER_RECORD:{i}")
|
| 489 |
+
valid_chain = False
|
| 490 |
+
continue
|
| 491 |
+
stored_prev = str(record.get("prev_hash") or "")
|
| 492 |
+
stored_hash = str(record.get("entry_sha256") or "")
|
| 493 |
+
raw = record.get("row")
|
| 494 |
+
computed = _sha({"prev_hash": stored_prev, "row": raw})
|
| 495 |
+
if stored_prev != prev or stored_hash != computed or not isinstance(raw, dict):
|
| 496 |
+
errors.append(f"CHAIN_MISMATCH:{i}")
|
| 497 |
+
valid_chain = False
|
| 498 |
+
continue
|
| 499 |
+
source = canonical["source_map"].get((str(raw.get("source_type")),
|
| 500 |
+
str(raw.get("source_entry_id"))))
|
| 501 |
+
doc = docs.get(str(raw.get("brain_node_id") or ""), {})
|
| 502 |
+
if source is None:
|
| 503 |
+
errors.append(f"SOURCE_BINDING_GONE:{i}")
|
| 504 |
+
valid_chain = False
|
| 505 |
+
continue
|
| 506 |
+
row, reasons = _row_core(raw, source, doc, "LOCAL_VALIDATED_APPEND")
|
| 507 |
+
if row is None or row.get("row_receipt_sha256") != raw.get("row_receipt_sha256"):
|
| 508 |
+
errors.append(f"ROW_REVALIDATION_FAILED:{i}:{','.join(reasons)}")
|
| 509 |
+
valid_chain = False
|
| 510 |
+
continue
|
| 511 |
+
row["ledger_entry_sha256"] = stored_hash
|
| 512 |
+
rows.append(row)
|
| 513 |
+
prev = stored_hash
|
| 514 |
+
return rows, {"chain_valid": valid_chain, "record_count": len(records),
|
| 515 |
+
"valid_row_count": len(rows), "head_sha256": prev,
|
| 516 |
+
"errors": errors}
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
def _split_group(row: Mapping[str, Any]) -> str:
|
| 520 |
+
group = f"{row['source_type']}|{row['source_entry_id']}|{row['entity_id']}"
|
| 521 |
+
bucket = int(hashlib.sha256(("split-v1|" + group).encode()).hexdigest()[:8], 16) % 10
|
| 522 |
+
return "train" if bucket < 7 else ("eval" if bucket < 9 else "test")
|
| 523 |
+
|
| 524 |
+
|
| 525 |
+
def _verify_optional_manifest(path: pathlib.Path, schema: str, dataset_hash: str,
|
| 526 |
+
model_hash: str | None = None) -> dict[str, Any]:
|
| 527 |
+
payload, error = _safe_read_json(path, 2 * 1024 * 1024)
|
| 528 |
+
if error:
|
| 529 |
+
return {"status": BLOCKED, "reasons": [error], "receipt_sha256": UNKNOWN}
|
| 530 |
+
reasons: list[str] = []
|
| 531 |
+
if not isinstance(payload, dict) or payload.get("schema_version") != schema:
|
| 532 |
+
reasons.append("SCHEMA_MISMATCH")
|
| 533 |
+
else:
|
| 534 |
+
body = {k: v for k, v in payload.items() if k != "content_sha256"}
|
| 535 |
+
if payload.get("content_sha256") != _sha(body): reasons.append("CONTENT_HASH_MISMATCH")
|
| 536 |
+
if payload.get("dataset_sha256") != dataset_hash: reasons.append("DATASET_HASH_MISMATCH")
|
| 537 |
+
if model_hash is not None and payload.get("model_sha256") != model_hash:
|
| 538 |
+
reasons.append("MODEL_HASH_MISMATCH")
|
| 539 |
+
return {"status": READY if not reasons else BLOCKED, "reasons": reasons,
|
| 540 |
+
"receipt_sha256": (payload or {}).get("receipt_sha256", UNKNOWN),
|
| 541 |
+
"manifest": payload if not reasons else None}
|
| 542 |
+
|
| 543 |
+
|
| 544 |
+
def build_dataset(ns: str = "a11oy", repo_root: pathlib.Path | str | None = None,
|
| 545 |
+
environ: Mapping[str, str] | None = None,
|
| 546 |
+
ledger_path: pathlib.Path | str | None = None) -> dict[str, Any]:
|
| 547 |
+
env = os.environ if environ is None else environ
|
| 548 |
+
canonical = _canonical_context(repo_root, env)
|
| 549 |
+
docs, doc_error = _brain_docs(ns)
|
| 550 |
+
if not canonical["complete"] or doc_error:
|
| 551 |
+
reasons = list(canonical["reasons"])
|
| 552 |
+
if doc_error: reasons.append(doc_error)
|
| 553 |
+
return {
|
| 554 |
+
"ok": True, "schema_version": SERVICE_SCHEMA, "label": UNAVAILABLE,
|
| 555 |
+
"rows": [], "dataset_sha256": None,
|
| 556 |
+
"dataset_readiness": {"status": BLOCKED, "reasons": sorted(set(reasons))},
|
| 557 |
+
"evaluation_readiness": {"status": BLOCKED, "reasons": ["DATASET_BLOCKED"]},
|
| 558 |
+
"model_readiness": {"status": BLOCKED, "reasons": ["DATASET_BLOCKED"]},
|
| 559 |
+
"split_counts": {"train": 0, "eval": 0, "test": 0},
|
| 560 |
+
"example_type_counts": {name: 0 for name in EXAMPLE_TYPES},
|
| 561 |
+
"quarantined_rows": [], "ledger": {"chain_valid": True, "record_count": 0},
|
| 562 |
+
"canonical_manifests_complete": canonical["complete"],
|
| 563 |
+
"training_triggered": False,
|
| 564 |
+
}
|
| 565 |
+
embedded, rejected = _load_embedded_rows(canonical, docs)
|
| 566 |
+
ledger = pathlib.Path(ledger_path).resolve() if ledger_path else _ledger_path(env)
|
| 567 |
+
appended, ledger_state = _load_local_rows(ledger, canonical, docs)
|
| 568 |
+
rows_by_receipt: dict[str, dict] = {}
|
| 569 |
+
for row in embedded + appended:
|
| 570 |
+
rows_by_receipt.setdefault(row["row_receipt_sha256"], row)
|
| 571 |
+
rows = list(rows_by_receipt.values())
|
| 572 |
+
for row in rows:
|
| 573 |
+
row["split"] = _split_group(row)
|
| 574 |
+
rows.sort(key=lambda r: (r["split"], r["source_type"], r["entity_id"], r["example_id"]))
|
| 575 |
+
type_counts = {name: sum(r["example_type"] == name for r in rows) for name in EXAMPLE_TYPES}
|
| 576 |
+
split_counts = {name: sum(r["split"] == name for r in rows) for name in ("train", "eval", "test")}
|
| 577 |
+
groups: dict[tuple[str, str, str], set[str]] = {}
|
| 578 |
+
for row in rows:
|
| 579 |
+
key = (row["source_type"], row["source_entry_id"], row["entity_id"])
|
| 580 |
+
groups.setdefault(key, set()).add(row["split"])
|
| 581 |
+
leakage = sum(len(v) > 1 for v in groups.values())
|
| 582 |
+
reasons = []
|
| 583 |
+
missing_types = [name for name, count in type_counts.items() if count == 0]
|
| 584 |
+
if not rows: reasons.append("ZERO_GROUNDED_ROWS")
|
| 585 |
+
if missing_types: reasons.append("MISSING_REQUIRED_EXAMPLE_TYPES:" + ",".join(missing_types))
|
| 586 |
+
if leakage: reasons.append(f"SOURCE_ENTITY_SPLIT_LEAKAGE:{leakage}")
|
| 587 |
+
if not ledger_state["chain_valid"]: reasons.append("LOCAL_LEDGER_CHAIN_INVALID")
|
| 588 |
+
dataset_hash = _sha([{k: row[k] for k in sorted(row) if k != "ledger_entry_sha256"}
|
| 589 |
+
for row in rows]) if rows else None
|
| 590 |
+
dataset_status = READY if not reasons else BLOCKED
|
| 591 |
+
|
| 592 |
+
model_path = _runtime_path("model-manifest.json", env,
|
| 593 |
+
"A11OY_BRAIN_RERANKER_MODEL_MANIFEST")
|
| 594 |
+
model = _verify_optional_manifest(model_path, MODEL_SCHEMA, dataset_hash or "") \
|
| 595 |
+
if dataset_status == READY else {"status": BLOCKED, "reasons": ["DATASET_BLOCKED"],
|
| 596 |
+
"receipt_sha256": UNKNOWN}
|
| 597 |
+
model_hash = ((model.get("manifest") or {}).get("model_sha256")
|
| 598 |
+
if model.get("status") == READY else None)
|
| 599 |
+
eval_path = _runtime_path("evaluation-manifest.json", env,
|
| 600 |
+
"A11OY_BRAIN_RERANKER_EVAL_MANIFEST")
|
| 601 |
+
if dataset_status != READY:
|
| 602 |
+
evaluation = {"status": BLOCKED, "reasons": ["DATASET_BLOCKED"],
|
| 603 |
+
"receipt_sha256": UNKNOWN}
|
| 604 |
+
elif model.get("status") != READY:
|
| 605 |
+
evaluation = {"status": BLOCKED, "reasons": ["MODEL_BLOCKED"],
|
| 606 |
+
"receipt_sha256": UNKNOWN}
|
| 607 |
+
elif not split_counts["test"]:
|
| 608 |
+
evaluation = {"status": BLOCKED, "reasons": ["TEST_SPLIT_EMPTY"],
|
| 609 |
+
"receipt_sha256": UNKNOWN}
|
| 610 |
+
else:
|
| 611 |
+
evaluation = _verify_optional_manifest(eval_path, EVAL_SCHEMA,
|
| 612 |
+
dataset_hash or "", model_hash)
|
| 613 |
+
return {
|
| 614 |
+
"ok": True, "schema_version": SERVICE_SCHEMA, "label": "MEASURED",
|
| 615 |
+
"rows": rows, "dataset_sha256": dataset_hash,
|
| 616 |
+
"dataset_readiness": {"status": dataset_status, "reasons": reasons},
|
| 617 |
+
"model_readiness": model, "evaluation_readiness": evaluation,
|
| 618 |
+
"split_counts": split_counts, "example_type_counts": type_counts,
|
| 619 |
+
"source_entity_group_count": len(groups), "split_leakage_group_count": leakage,
|
| 620 |
+
"quarantined_rows": rejected, "ledger": ledger_state,
|
| 621 |
+
"canonical_manifests_complete": True, "training_triggered": False,
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
|
| 625 |
+
def append_validated_row(payload: Mapping[str, Any], ns: str = "a11oy",
|
| 626 |
+
repo_root: pathlib.Path | str | None = None,
|
| 627 |
+
environ: Mapping[str, str] | None = None,
|
| 628 |
+
ledger_path: pathlib.Path | str | None = None) -> tuple[dict, int]:
|
| 629 |
+
"""Append one hash-bound row after revalidating all local source bytes."""
|
| 630 |
+
env = os.environ if environ is None else environ
|
| 631 |
+
canonical = _canonical_context(repo_root, env)
|
| 632 |
+
if not canonical["complete"]:
|
| 633 |
+
return {"ok": False, "status": BLOCKED, "reasons": canonical["reasons"],
|
| 634 |
+
"row": None}, 503
|
| 635 |
+
docs, doc_error = _brain_docs(ns)
|
| 636 |
+
if doc_error:
|
| 637 |
+
return {"ok": False, "status": BLOCKED, "reasons": [doc_error], "row": None}, 503
|
| 638 |
+
source = canonical["source_map"].get((str(payload.get("source_type") or ""),
|
| 639 |
+
str(payload.get("source_entry_id") or "")))
|
| 640 |
+
if source is None:
|
| 641 |
+
return {"ok": False, "status": BLOCKED, "reasons": ["SOURCE_BINDING_NOT_VERIFIED"],
|
| 642 |
+
"row": None}, 422
|
| 643 |
+
required_hashes = {
|
| 644 |
+
"source_manifest_sha256": source["manifest_sha256"],
|
| 645 |
+
"source_artifact_sha256": source["artifact_sha256"],
|
| 646 |
+
}
|
| 647 |
+
mismatch = [key + "_MISMATCH" for key, expected in required_hashes.items()
|
| 648 |
+
if str(payload.get(key) or "").lower() != expected]
|
| 649 |
+
doc = docs.get(str(payload.get("brain_node_id") or ""), {})
|
| 650 |
+
row, reasons = _row_core(payload, source, doc, "LOCAL_VALIDATED_APPEND")
|
| 651 |
+
if mismatch or row is None:
|
| 652 |
+
return {"ok": False, "status": BLOCKED,
|
| 653 |
+
"reasons": sorted(set(mismatch + reasons)), "row": None}, 422
|
| 654 |
+
path = pathlib.Path(ledger_path).resolve() if ledger_path else _ledger_path(env)
|
| 655 |
+
with _LOCK:
|
| 656 |
+
existing, state = _load_local_rows(path, canonical, docs)
|
| 657 |
+
if not state["chain_valid"]:
|
| 658 |
+
return {"ok": False, "status": BLOCKED,
|
| 659 |
+
"reasons": ["LOCAL_LEDGER_CHAIN_INVALID"], "row": None}, 409
|
| 660 |
+
if state["record_count"] >= MAX_LOCAL_ROWS:
|
| 661 |
+
return {"ok": False, "status": BLOCKED,
|
| 662 |
+
"reasons": ["LOCAL_ROW_LIMIT_REACHED"], "row": None}, 429
|
| 663 |
+
if any(r["row_receipt_sha256"] == row["row_receipt_sha256"] for r in existing):
|
| 664 |
+
return {"ok": True, "status": READY, "duplicate": True, "row": row}, 200
|
| 665 |
+
prev = state["head_sha256"]
|
| 666 |
+
record = {"schema_version": LEDGER_SCHEMA, "prev_hash": prev, "row": row}
|
| 667 |
+
record["entry_sha256"] = _sha({"prev_hash": prev, "row": row})
|
| 668 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 669 |
+
with path.open("a", encoding="utf-8", newline="\n") as handle:
|
| 670 |
+
handle.write(json.dumps(record, sort_keys=True, ensure_ascii=False) + "\n")
|
| 671 |
+
handle.flush()
|
| 672 |
+
os.fsync(handle.fileno())
|
| 673 |
+
return {"ok": True, "status": READY, "duplicate": False,
|
| 674 |
+
"row": {**row, "ledger_entry_sha256": record["entry_sha256"]}}, 201
|
| 675 |
+
|
| 676 |
+
|
| 677 |
+
def _last_feed_state(path: pathlib.Path) -> dict[str, Any]:
|
| 678 |
+
records, errors = _read_jsonl(path, MAX_LEDGER_BYTES)
|
| 679 |
+
prev = "0" * 64
|
| 680 |
+
valid = not errors
|
| 681 |
+
last = None
|
| 682 |
+
for i, record in enumerate(records):
|
| 683 |
+
if not isinstance(record, dict) or record.get("schema_version") != FEED_SCHEMA:
|
| 684 |
+
valid = False; errors.append(f"INVALID_FEED_RECORD:{i}"); continue
|
| 685 |
+
stored = str(record.get("receipt_sha256") or "")
|
| 686 |
+
body = {k: v for k, v in record.items() if k != "receipt_sha256"}
|
| 687 |
+
if record.get("prev_hash") != prev or stored != _sha(body):
|
| 688 |
+
valid = False; errors.append(f"FEED_CHAIN_MISMATCH:{i}"); continue
|
| 689 |
+
prev, last = stored, record
|
| 690 |
+
return {"chain_valid": valid, "record_count": len(records), "head_sha256": prev,
|
| 691 |
+
"last": last, "errors": errors}
|
| 692 |
+
|
| 693 |
+
|
| 694 |
+
def feed_status(ns: str = "a11oy", repo_root: pathlib.Path | str | None = None,
|
| 695 |
+
environ: Mapping[str, str] | None = None,
|
| 696 |
+
feed_path: pathlib.Path | str | None = None) -> dict[str, Any]:
|
| 697 |
+
env = os.environ if environ is None else environ
|
| 698 |
+
path = pathlib.Path(feed_path).resolve() if feed_path else _feed_path(env)
|
| 699 |
+
state = _last_feed_state(path)
|
| 700 |
+
enabled = str(env.get("A11OY_BRAIN_FEED_ENABLED", "0")).strip().lower() in {"1", "true", "yes"}
|
| 701 |
+
killed = str(env.get("A11OY_BRAIN_FEED_KILL_SWITCH", "1")).strip().lower() not in {"0", "false", "no"}
|
| 702 |
+
last = state.get("last") or {}
|
| 703 |
+
return {
|
| 704 |
+
"ok": True, "schema_version": FEED_SCHEMA,
|
| 705 |
+
"status": (DEGRADED if enabled and not killed and state["chain_valid"] else UNAVAILABLE),
|
| 706 |
+
"enabled": enabled, "kill_switch_engaged": killed,
|
| 707 |
+
"network_access": False, "training_trigger": False,
|
| 708 |
+
"stages": list(FEED_STAGES),
|
| 709 |
+
"bounds": {"node_budget": FEED_NODE_BUDGET, "per_source_budget": FEED_SOURCE_BUDGET,
|
| 710 |
+
"minimum_interval_seconds": FEED_MIN_INTERVAL_S,
|
| 711 |
+
"maximum_backoff_seconds": FEED_MAX_BACKOFF_S,
|
| 712 |
+
"network_rate_limit": "ZERO_NETWORK_REQUESTS"},
|
| 713 |
+
"checkpoint": last.get("checkpoint", "NOT_STARTED"),
|
| 714 |
+
"last_successful_receipt": last.get("receipt_sha256", UNKNOWN),
|
| 715 |
+
"last_inventory_sha256": last.get("inventory_sha256", UNKNOWN),
|
| 716 |
+
"admitted_count": last.get("admitted_count", 0),
|
| 717 |
+
"quarantined_count": last.get("quarantined_count", 0),
|
| 718 |
+
"freshness_state": last.get("freshness_state", UNKNOWN),
|
| 719 |
+
"next_refresh_utc": last.get("next_refresh_utc", UNKNOWN),
|
| 720 |
+
"backoff_seconds": last.get("backoff_seconds", 0),
|
| 721 |
+
"receipt_chain": {k: state[k] for k in ("chain_valid", "record_count", "head_sha256", "errors")},
|
| 722 |
+
}
|
| 723 |
+
|
| 724 |
+
|
| 725 |
+
def refresh_feed(ns: str = "a11oy", repo_root: pathlib.Path | str | None = None,
|
| 726 |
+
environ: Mapping[str, str] | None = None,
|
| 727 |
+
feed_path: pathlib.Path | str | None = None) -> tuple[dict, int]:
|
| 728 |
+
"""Run one bounded local-only cycle; no network fetch and no training trigger."""
|
| 729 |
+
env = os.environ if environ is None else environ
|
| 730 |
+
path = pathlib.Path(feed_path).resolve() if feed_path else _feed_path(env)
|
| 731 |
+
status = feed_status(ns, repo_root, env, path)
|
| 732 |
+
if not status["enabled"] or status["kill_switch_engaged"]:
|
| 733 |
+
return {**status, "ok": False, "reason": "FEED_DISABLED_OR_KILLED"}, 503
|
| 734 |
+
state = _last_feed_state(path)
|
| 735 |
+
last = state.get("last") or {}
|
| 736 |
+
now = time.time()
|
| 737 |
+
try:
|
| 738 |
+
last_epoch = datetime.datetime.fromisoformat(str(last.get("completed_at"))).timestamp()
|
| 739 |
+
except Exception:
|
| 740 |
+
last_epoch = 0.0
|
| 741 |
+
if last_epoch and now - last_epoch < FEED_MIN_INTERVAL_S:
|
| 742 |
+
return {**status, "ok": False, "reason": "REFRESH_RATE_LIMITED"}, 429
|
| 743 |
+
inventory = build_inventory(ns, repo_root, env)
|
| 744 |
+
if inventory["inventory"]["raw_node_count"] > FEED_NODE_BUDGET:
|
| 745 |
+
return {**status, "ok": False, "reason": "NODE_BUDGET_EXCEEDED"}, 503
|
| 746 |
+
dataset = build_dataset(ns, repo_root, env)
|
| 747 |
+
completed = _now()
|
| 748 |
+
next_refresh = (datetime.datetime.now(datetime.timezone.utc) +
|
| 749 |
+
datetime.timedelta(seconds=FEED_MIN_INTERVAL_S)).isoformat()
|
| 750 |
+
record = {
|
| 751 |
+
"schema_version": FEED_SCHEMA,
|
| 752 |
+
"prev_hash": state["head_sha256"],
|
| 753 |
+
"checkpoint": f"inventory:{inventory['inventory_sha256']}:rows:{len(dataset['rows'])}",
|
| 754 |
+
"completed_at": completed,
|
| 755 |
+
"inventory_sha256": inventory["inventory_sha256"],
|
| 756 |
+
"dataset_sha256": dataset.get("dataset_sha256") or UNKNOWN,
|
| 757 |
+
"raw_node_count": inventory["inventory"]["raw_node_count"],
|
| 758 |
+
"admitted_count": inventory["inventory"]["raw_node_count"] - inventory["inventory"]["quarantined_node_count"],
|
| 759 |
+
"quarantined_count": inventory["inventory"]["quarantined_node_count"],
|
| 760 |
+
"dataset_row_count": len(dataset["rows"]),
|
| 761 |
+
"dataset_status": dataset["dataset_readiness"]["status"],
|
| 762 |
+
"freshness_state": ("VERIFIED_SOURCE_TIMESTAMPS_PRESENT" if any(
|
| 763 |
+
d["freshness_basis"] == "SOURCE_TIMESTAMP" for d in inventory["decisions"]
|
| 764 |
+
) else "UNVERIFIED"),
|
| 765 |
+
"next_refresh_utc": next_refresh,
|
| 766 |
+
"backoff_seconds": 0,
|
| 767 |
+
"source_policy": {"network": "DENIED", "robots": "NOT_APPLICABLE_LOCAL_SNAPSHOT",
|
| 768 |
+
"license_unknown_quarantined": True, "provenance_required": True},
|
| 769 |
+
"stage_results": [
|
| 770 |
+
{"stage": stage, "status": (READY if stage != "EVALUATE" or
|
| 771 |
+
dataset["evaluation_readiness"]["status"] == READY
|
| 772 |
+
else BLOCKED)}
|
| 773 |
+
for stage in FEED_STAGES
|
| 774 |
+
],
|
| 775 |
+
"training_triggered": False,
|
| 776 |
+
}
|
| 777 |
+
record["receipt_sha256"] = _sha(record)
|
| 778 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 779 |
+
with _LOCK:
|
| 780 |
+
with path.open("a", encoding="utf-8", newline="\n") as handle:
|
| 781 |
+
handle.write(json.dumps(record, sort_keys=True, ensure_ascii=False) + "\n")
|
| 782 |
+
handle.flush(); os.fsync(handle.fileno())
|
| 783 |
+
return {"ok": True, "status": DEGRADED, "receipt": record,
|
| 784 |
+
"note": "Local evidence checkpoint written; no network or training occurred."}, 201
|
| 785 |
+
|
| 786 |
+
|
| 787 |
+
def anatomy_receipt(node_id: str, ns: str = "a11oy",
|
| 788 |
+
repo_root: pathlib.Path | str | None = None,
|
| 789 |
+
environ: Mapping[str, str] | None = None,
|
| 790 |
+
feed_path: pathlib.Path | str | None = None) -> tuple[dict, int]:
|
| 791 |
+
inventory = build_inventory(ns, repo_root, environ)
|
| 792 |
+
item = next((d for d in inventory["decisions"] if d["brain_node_id"] == node_id), None)
|
| 793 |
+
if item is None:
|
| 794 |
+
return {"ok": False, "status": UNAVAILABLE, "reason": "NODE_NOT_FOUND",
|
| 795 |
+
"receipt_sha256": UNKNOWN}, 404
|
| 796 |
+
feed = feed_status(ns, repo_root, environ, feed_path)
|
| 797 |
+
loop_receipt = (feed["last_successful_receipt"]
|
| 798 |
+
if feed["last_inventory_sha256"] == inventory["inventory_sha256"]
|
| 799 |
+
else UNKNOWN)
|
| 800 |
+
payload = {
|
| 801 |
+
**item,
|
| 802 |
+
"inventory_sha256": inventory["inventory_sha256"],
|
| 803 |
+
"loop_checkpoint": feed["checkpoint"],
|
| 804 |
+
"loop_receipt_sha256": loop_receipt,
|
| 805 |
+
"receipt_state": "VERIFIED_CHAIN_REFERENCE" if loop_receipt != UNKNOWN else UNVERIFIED,
|
| 806 |
+
"model_receipt_sha256": UNKNOWN,
|
| 807 |
+
"evaluation_receipt_sha256": UNKNOWN,
|
| 808 |
+
"note": "GET returns existing deterministic anatomy and loop linkage; it mints no receipt.",
|
| 809 |
+
}
|
| 810 |
+
return {"ok": True, "label": inventory["label"], "receipt_anatomy": payload,
|
| 811 |
+
"receipt_sha256": loop_receipt}, 200
|
| 812 |
+
|
| 813 |
+
|
| 814 |
+
def service_status(ns: str = "a11oy", repo_root: pathlib.Path | str | None = None,
|
| 815 |
+
environ: Mapping[str, str] | None = None) -> dict[str, Any]:
|
| 816 |
+
dataset = build_dataset(ns, repo_root, environ)
|
| 817 |
+
inventory = build_inventory(ns, repo_root, environ)
|
| 818 |
+
feed = feed_status(ns, repo_root, environ)
|
| 819 |
+
readiness = (
|
| 820 |
+
dataset["dataset_readiness"]["status"],
|
| 821 |
+
dataset["model_readiness"]["status"],
|
| 822 |
+
dataset["evaluation_readiness"]["status"],
|
| 823 |
+
)
|
| 824 |
+
operational = all(state == READY for state in readiness)
|
| 825 |
+
return {
|
| 826 |
+
"ok": True, "schema_version": SERVICE_SCHEMA,
|
| 827 |
+
# The inventory can be measured while the train/eval/model pipeline is still
|
| 828 |
+
# unavailable. Keep those truths separate so the estate rollup cannot turn
|
| 829 |
+
# a measured node count into an operational model claim.
|
| 830 |
+
"status": READY if operational else BLOCKED,
|
| 831 |
+
"label": "MEASURED" if operational else UNAVAILABLE,
|
| 832 |
+
"inventory_label": inventory["label"],
|
| 833 |
+
"inventory": inventory["inventory"],
|
| 834 |
+
"inventory_sha256": inventory["inventory_sha256"],
|
| 835 |
+
"dataset": {"status": dataset["dataset_readiness"]["status"],
|
| 836 |
+
"reasons": dataset["dataset_readiness"]["reasons"],
|
| 837 |
+
"row_count": len(dataset["rows"]),
|
| 838 |
+
"dataset_sha256": dataset.get("dataset_sha256"),
|
| 839 |
+
"split_counts": dataset["split_counts"],
|
| 840 |
+
"example_type_counts": dataset["example_type_counts"]},
|
| 841 |
+
"evaluation": dataset["evaluation_readiness"],
|
| 842 |
+
"model": dataset["model_readiness"],
|
| 843 |
+
"feed": feed,
|
| 844 |
+
"training_triggered": False,
|
| 845 |
+
}
|
| 846 |
+
|
| 847 |
+
|
| 848 |
+
def info() -> dict[str, Any]:
|
| 849 |
+
return {
|
| 850 |
+
"service": "a11oy.brain.evidence-reranker",
|
| 851 |
+
"schema_version": SERVICE_SCHEMA,
|
| 852 |
+
"readiness_dimensions": ["dataset", "evaluation", "model"],
|
| 853 |
+
"required_example_types": list(EXAMPLE_TYPES),
|
| 854 |
+
"split_rule": "sha256(source_type|source_entry_id|entity_id), 70/20/10",
|
| 855 |
+
"feed_stages": list(FEED_STAGES),
|
| 856 |
+
"network_access": False, "training_trigger": False,
|
| 857 |
+
"write_paths": ["loopback validated-row append", "loopback feed checkpoint"],
|
| 858 |
+
"bounds": {"local_rows": MAX_LOCAL_ROWS, "inventory_page": MAX_INVENTORY_PAGE,
|
| 859 |
+
"dataset_page": MAX_DATASET_PAGE, "node_budget": FEED_NODE_BUDGET},
|
| 860 |
+
"honesty": "Missing canonical manifests or hashes => BLOCKED with zero rows.",
|
| 861 |
+
}
|
| 862 |
+
|
| 863 |
+
|
| 864 |
+
def _loopback(host: Any) -> bool:
|
| 865 |
+
value = str(host or "").strip().lower()
|
| 866 |
+
if value in {"localhost", "testclient", "testserver"}: return True
|
| 867 |
+
try:
|
| 868 |
+
return ipaddress.ip_address(value).is_loopback
|
| 869 |
+
except ValueError:
|
| 870 |
+
return False
|
| 871 |
+
|
| 872 |
+
|
| 873 |
+
def _local_request(request: Any) -> bool:
|
| 874 |
+
"""Require both transport peer and Host/URL to be loopback.
|
| 875 |
+
|
| 876 |
+
Checking only ``request.client`` is not sufficient behind a same-host reverse
|
| 877 |
+
proxy: a public request can otherwise appear to originate from 127.0.0.1.
|
| 878 |
+
"""
|
| 879 |
+
client_host = getattr(getattr(request, "client", None), "host", None)
|
| 880 |
+
url_host = getattr(getattr(request, "url", None), "hostname", None)
|
| 881 |
+
return _loopback(client_host) and _loopback(url_host)
|
| 882 |
+
|
| 883 |
+
|
| 884 |
+
def register(app: Any, ns: str = "a11oy") -> list[str]:
|
| 885 |
+
"""Register bounded API routes before the SPA catch-all."""
|
| 886 |
+
from fastapi.responses import JSONResponse
|
| 887 |
+
base = f"/api/{ns}/v1/brain/reranker"
|
| 888 |
+
paths: list[str] = []
|
| 889 |
+
|
| 890 |
+
@app.get(base + "/info")
|
| 891 |
+
def _info():
|
| 892 |
+
return JSONResponse(info())
|
| 893 |
+
paths.append(base + "/info")
|
| 894 |
+
|
| 895 |
+
@app.get(base + "/status")
|
| 896 |
+
def _status():
|
| 897 |
+
return JSONResponse(service_status(ns))
|
| 898 |
+
paths.append(base + "/status")
|
| 899 |
+
|
| 900 |
+
# The holographic/frontier registry matches a surface id by exact route
|
| 901 |
+
# segment. This additive alias makes the ``brainreranker`` surface visible
|
| 902 |
+
# to the estate status rollup while the structured canonical API remains
|
| 903 |
+
# ``/brain/reranker/status``.
|
| 904 |
+
@app.get(f"/api/{ns}/v1/brainreranker/status")
|
| 905 |
+
def _surface_status():
|
| 906 |
+
return JSONResponse(service_status(ns))
|
| 907 |
+
paths.append(f"/api/{ns}/v1/brainreranker/status")
|
| 908 |
+
|
| 909 |
+
@app.get(base + "/inventory")
|
| 910 |
+
def _inventory(offset: int = 0, limit: int = 100, decision: str = ""):
|
| 911 |
+
result = build_inventory(ns)
|
| 912 |
+
selected = result["decisions"]
|
| 913 |
+
if decision:
|
| 914 |
+
selected = [d for d in selected if d["admission_decision"] == decision.upper()]
|
| 915 |
+
start = max(0, int(offset)); page = selected[start:start + max(1, min(MAX_INVENTORY_PAGE, int(limit)))]
|
| 916 |
+
return JSONResponse({k: v for k, v in result.items() if k != "decisions"} | {
|
| 917 |
+
"offset": start, "limit": len(page), "total": len(selected),
|
| 918 |
+
"next_offset": start + len(page) if start + len(page) < len(selected) else None,
|
| 919 |
+
"decisions": page,
|
| 920 |
+
})
|
| 921 |
+
paths.append(base + "/inventory")
|
| 922 |
+
|
| 923 |
+
@app.get(base + "/dataset")
|
| 924 |
+
def _dataset(split: str = "", offset: int = 0, limit: int = 100):
|
| 925 |
+
result = build_dataset(ns)
|
| 926 |
+
selected = result["rows"]
|
| 927 |
+
if split:
|
| 928 |
+
selected = [r for r in selected if r["split"] == split.lower()]
|
| 929 |
+
start = max(0, int(offset)); page = selected[start:start + max(1, min(MAX_DATASET_PAGE, int(limit)))]
|
| 930 |
+
return JSONResponse({k: v for k, v in result.items() if k != "rows"} | {
|
| 931 |
+
"offset": start, "limit": len(page), "total": len(selected),
|
| 932 |
+
"next_offset": start + len(page) if start + len(page) < len(selected) else None,
|
| 933 |
+
"rows": page,
|
| 934 |
+
})
|
| 935 |
+
paths.append(base + "/dataset")
|
| 936 |
+
|
| 937 |
+
@app.get(base + "/feed")
|
| 938 |
+
def _feed():
|
| 939 |
+
return JSONResponse(feed_status(ns))
|
| 940 |
+
paths.append(base + "/feed")
|
| 941 |
+
|
| 942 |
+
@app.get(f"/api/{ns}/v1/anatomy/brain-receipt/{{node_id:path}}")
|
| 943 |
+
def _anatomy(node_id: str):
|
| 944 |
+
body, status = anatomy_receipt(node_id, ns)
|
| 945 |
+
return JSONResponse(body, status_code=status)
|
| 946 |
+
paths.append(f"/api/{ns}/v1/anatomy/brain-receipt/{{node_id:path}}")
|
| 947 |
+
|
| 948 |
+
async def _append(request):
|
| 949 |
+
if not _local_request(request):
|
| 950 |
+
return JSONResponse({"ok": False, "status": BLOCKED,
|
| 951 |
+
"reasons": ["LOCAL_CLIENT_REQUIRED"]}, status_code=403)
|
| 952 |
+
try:
|
| 953 |
+
payload = await request.json()
|
| 954 |
+
except Exception:
|
| 955 |
+
payload = None
|
| 956 |
+
if not isinstance(payload, dict):
|
| 957 |
+
return JSONResponse({"ok": False, "status": BLOCKED,
|
| 958 |
+
"reasons": ["JSON_OBJECT_REQUIRED"]}, status_code=400)
|
| 959 |
+
body, status = append_validated_row(payload, ns)
|
| 960 |
+
return JSONResponse(body, status_code=status)
|
| 961 |
+
|
| 962 |
+
async def _refresh(request):
|
| 963 |
+
if not _local_request(request):
|
| 964 |
+
return JSONResponse({"ok": False, "status": BLOCKED,
|
| 965 |
+
"reason": "LOCAL_CLIENT_REQUIRED"}, status_code=403)
|
| 966 |
+
body, status = refresh_feed(ns)
|
| 967 |
+
return JSONResponse(body, status_code=status)
|
| 968 |
+
|
| 969 |
+
try:
|
| 970 |
+
import fastapi
|
| 971 |
+
_append.__annotations__["request"] = fastapi.Request
|
| 972 |
+
_refresh.__annotations__["request"] = fastapi.Request
|
| 973 |
+
except Exception:
|
| 974 |
+
pass
|
| 975 |
+
app.router.add_route(base + "/rows", _append, methods=["POST"])
|
| 976 |
+
app.router.add_route(base + "/feed/refresh", _refresh, methods=["POST"])
|
| 977 |
+
paths.extend([base + "/rows", base + "/feed/refresh"])
|
| 978 |
+
return paths
|
|
@@ -0,0 +1,1221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 3 |
+
"""Bounded, deterministic admission for Brain-derived train/eval rows.
|
| 4 |
+
|
| 5 |
+
This module does not turn raw Brain inventory into training data. It evaluates
|
| 6 |
+
caller-supplied JSON/JSONL candidates and admits a row only when every required
|
| 7 |
+
provenance, rights, freshness, contamination, deduplication, and split
|
| 8 |
+
obligation is established by pinned, allowlisted Ed25519 evidence and a signed
|
| 9 |
+
cross-run split ledger. Missing evidence is a reason-coded quarantine
|
| 10 |
+
decision; it is never guessed or filled in.
|
| 11 |
+
|
| 12 |
+
The gate performs no network access, starts no training, and grants no proof or
|
| 13 |
+
model-promotion credit.
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
from __future__ import annotations
|
| 17 |
+
|
| 18 |
+
import argparse
|
| 19 |
+
import base64
|
| 20 |
+
import binascii
|
| 21 |
+
import collections
|
| 22 |
+
import dataclasses
|
| 23 |
+
import datetime as dt
|
| 24 |
+
import hashlib
|
| 25 |
+
import json
|
| 26 |
+
import os
|
| 27 |
+
import pathlib
|
| 28 |
+
import re
|
| 29 |
+
from typing import Any, Iterable, Mapping, Sequence
|
| 30 |
+
from urllib.parse import urlsplit
|
| 31 |
+
|
| 32 |
+
from cryptography.exceptions import InvalidSignature
|
| 33 |
+
from cryptography.hazmat.primitives import serialization
|
| 34 |
+
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
CANDIDATE_SCHEMA = "szl.brain-training-candidate.v1"
|
| 38 |
+
DECISION_SCHEMA = "szl.brain-training-admission-decision.v1"
|
| 39 |
+
REPORT_SCHEMA = "szl.brain-training-admission-report.v1"
|
| 40 |
+
SOURCE_EVIDENCE_SCHEMA = "szl.source-revision-evidence.v2"
|
| 41 |
+
RIGHTS_EVIDENCE_SCHEMA = "szl.rights-evidence.v2"
|
| 42 |
+
CONTAMINATION_EVIDENCE_SCHEMA = "szl.contamination-evidence.v2"
|
| 43 |
+
SPLIT_LEDGER_SCHEMA = "szl.brain-training-split-ledger.v1"
|
| 44 |
+
TRUST_STORE_SCHEMA = "szl.evidence-trust-store.v1"
|
| 45 |
+
SIGNATURE_ALGORITHM = "Ed25519"
|
| 46 |
+
|
| 47 |
+
MAX_INPUT_BYTES = 32 * 1024 * 1024
|
| 48 |
+
MAX_ROWS = 20_000
|
| 49 |
+
MAX_ROW_BYTES = 256 * 1024
|
| 50 |
+
MAX_CONTENT_BYTES = 64 * 1024
|
| 51 |
+
MAX_EVIDENCE_BYTES = 4 * 1024 * 1024
|
| 52 |
+
MAX_REFERENCES = 64
|
| 53 |
+
|
| 54 |
+
DEFAULT_RIGHTS_BASES = ("PROJECT_AUTHORED_SCHEMA_GENERATED",)
|
| 55 |
+
DEFAULT_LICENSES = ("Apache-2.0",)
|
| 56 |
+
SPLITS = frozenset({"TRAIN", "EVAL"})
|
| 57 |
+
|
| 58 |
+
_SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
|
| 59 |
+
_REVISION_RE = re.compile(r"^(?:git:[0-9a-f]{40,64}|sha256:[0-9a-f]{64})$")
|
| 60 |
+
_NODE_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:/@+\-]{2,255}$")
|
| 61 |
+
_METHOD_RE = re.compile(r"^[A-Z0-9][A-Z0-9._:\-]{2,127}$")
|
| 62 |
+
_REFERENCE_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:/@+\-]{1,255}$")
|
| 63 |
+
|
| 64 |
+
_ROW_FIELDS = frozenset(
|
| 65 |
+
{
|
| 66 |
+
"schema_version",
|
| 67 |
+
"node_id",
|
| 68 |
+
"content",
|
| 69 |
+
"content_sha256",
|
| 70 |
+
"source",
|
| 71 |
+
"rights",
|
| 72 |
+
"contamination",
|
| 73 |
+
"split",
|
| 74 |
+
}
|
| 75 |
+
)
|
| 76 |
+
_SOURCE_FIELDS = frozenset({"uri", "revision", "timestamp_utc", "evidence"})
|
| 77 |
+
_RIGHTS_FIELDS = frozenset({"basis", "license", "evidence"})
|
| 78 |
+
_CONTAMINATION_FIELDS = frozenset(
|
| 79 |
+
{"result", "method", "checked_against", "evidence"}
|
| 80 |
+
)
|
| 81 |
+
_SIGNED_ENVELOPE_FIELDS = frozenset(
|
| 82 |
+
{"schema_version", "issuer", "tool_identity", "issued_at_utc", "statement", "signature"}
|
| 83 |
+
)
|
| 84 |
+
_SIGNATURE_FIELDS = frozenset({"algorithm", "key_id", "value_base64"})
|
| 85 |
+
_RUN_RECEIPT_FIELDS = frozenset(
|
| 86 |
+
{
|
| 87 |
+
"run_id",
|
| 88 |
+
"completed_at_utc",
|
| 89 |
+
"tool_identity",
|
| 90 |
+
"method",
|
| 91 |
+
"candidate_content_sha256",
|
| 92 |
+
"checked_against_sha256",
|
| 93 |
+
"result",
|
| 94 |
+
}
|
| 95 |
+
)
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
class AdmissionInputError(RuntimeError):
|
| 99 |
+
"""A bounded file-level input obligation failed before row evaluation."""
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
@dataclasses.dataclass(frozen=True)
|
| 103 |
+
class TrustedEvidenceSigner:
|
| 104 |
+
"""Pinned public-key identity allowed to issue admission evidence."""
|
| 105 |
+
|
| 106 |
+
key_id: str
|
| 107 |
+
issuer: str
|
| 108 |
+
tool_identity: str
|
| 109 |
+
public_key_path: str
|
| 110 |
+
public_key_sha256: str
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
@dataclasses.dataclass(frozen=True)
|
| 114 |
+
class AdmissionPolicy:
|
| 115 |
+
"""Frozen policy inputs; ``as_of_utc`` is required for reproducibility."""
|
| 116 |
+
|
| 117 |
+
as_of_utc: str
|
| 118 |
+
evidence_root: pathlib.Path | str
|
| 119 |
+
max_age_days: int = 365
|
| 120 |
+
allowed_rights_bases: tuple[str, ...] = DEFAULT_RIGHTS_BASES
|
| 121 |
+
allowed_licenses: tuple[str, ...] = DEFAULT_LICENSES
|
| 122 |
+
protected_eval_content_sha256: frozenset[str] = frozenset()
|
| 123 |
+
trusted_evidence_signers: tuple[TrustedEvidenceSigner, ...] = ()
|
| 124 |
+
split_ledger_evidence: Mapping[str, str] | None = None
|
| 125 |
+
|
| 126 |
+
def __post_init__(self) -> None:
|
| 127 |
+
as_of = _parse_utc(self.as_of_utc)
|
| 128 |
+
if as_of is None:
|
| 129 |
+
raise AdmissionInputError("POLICY_AS_OF_UTC_INVALID")
|
| 130 |
+
if not isinstance(self.max_age_days, int) or not 0 <= self.max_age_days <= 3650:
|
| 131 |
+
raise AdmissionInputError("POLICY_MAX_AGE_DAYS_INVALID")
|
| 132 |
+
root = pathlib.Path(self.evidence_root).resolve()
|
| 133 |
+
if not root.is_dir():
|
| 134 |
+
raise AdmissionInputError("POLICY_EVIDENCE_ROOT_UNAVAILABLE")
|
| 135 |
+
bases = tuple(sorted(set(self.allowed_rights_bases)))
|
| 136 |
+
licenses = tuple(sorted(set(self.allowed_licenses)))
|
| 137 |
+
if not bases or not licenses or any(not value for value in (*bases, *licenses)):
|
| 138 |
+
raise AdmissionInputError("POLICY_RIGHTS_ALLOWLIST_INVALID")
|
| 139 |
+
protected = frozenset(self.protected_eval_content_sha256)
|
| 140 |
+
if any(not _is_sha256(value) for value in protected):
|
| 141 |
+
raise AdmissionInputError("POLICY_PROTECTED_EVAL_HASH_INVALID")
|
| 142 |
+
signers = tuple(self.trusted_evidence_signers)
|
| 143 |
+
if not signers:
|
| 144 |
+
# Empty trust is valid policy construction, but every signed evidence
|
| 145 |
+
# check will fail closed. This keeps inspection-only use possible.
|
| 146 |
+
pass
|
| 147 |
+
if len({item.key_id for item in signers}) != len(signers):
|
| 148 |
+
raise AdmissionInputError("POLICY_SIGNER_KEY_ID_DUPLICATE")
|
| 149 |
+
for signer in signers:
|
| 150 |
+
if not all(
|
| 151 |
+
isinstance(value, str) and value.strip()
|
| 152 |
+
for value in (signer.key_id, signer.issuer, signer.tool_identity)
|
| 153 |
+
):
|
| 154 |
+
raise AdmissionInputError("POLICY_SIGNER_IDENTITY_INVALID")
|
| 155 |
+
if not _is_sha256(signer.public_key_sha256):
|
| 156 |
+
raise AdmissionInputError("POLICY_SIGNER_PUBLIC_KEY_SHA256_INVALID")
|
| 157 |
+
key_path = _safe_evidence_path(root, signer.public_key_path)
|
| 158 |
+
if key_path is None or not key_path.is_file():
|
| 159 |
+
raise AdmissionInputError("POLICY_SIGNER_PUBLIC_KEY_UNAVAILABLE")
|
| 160 |
+
if sha256_file(key_path) != signer.public_key_sha256:
|
| 161 |
+
raise AdmissionInputError("POLICY_SIGNER_PUBLIC_KEY_HASH_MISMATCH")
|
| 162 |
+
try:
|
| 163 |
+
key = serialization.load_pem_public_key(key_path.read_bytes())
|
| 164 |
+
except (OSError, ValueError, TypeError) as exc:
|
| 165 |
+
raise AdmissionInputError("POLICY_SIGNER_PUBLIC_KEY_INVALID") from exc
|
| 166 |
+
if not isinstance(key, Ed25519PublicKey):
|
| 167 |
+
raise AdmissionInputError("POLICY_SIGNER_PUBLIC_KEY_NOT_ED25519")
|
| 168 |
+
ledger_descriptor = self.split_ledger_evidence
|
| 169 |
+
if ledger_descriptor is not None and (
|
| 170 |
+
not isinstance(ledger_descriptor, Mapping)
|
| 171 |
+
or set(ledger_descriptor) != {"path", "sha256"}
|
| 172 |
+
):
|
| 173 |
+
raise AdmissionInputError("POLICY_SPLIT_LEDGER_DESCRIPTOR_INVALID")
|
| 174 |
+
object.__setattr__(self, "as_of_utc", _format_utc(as_of))
|
| 175 |
+
object.__setattr__(self, "evidence_root", root)
|
| 176 |
+
object.__setattr__(self, "allowed_rights_bases", bases)
|
| 177 |
+
object.__setattr__(self, "allowed_licenses", licenses)
|
| 178 |
+
object.__setattr__(self, "protected_eval_content_sha256", protected)
|
| 179 |
+
object.__setattr__(self, "trusted_evidence_signers", signers)
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
def canonical_bytes(value: Any) -> bytes:
|
| 183 |
+
return json.dumps(
|
| 184 |
+
value, ensure_ascii=False, sort_keys=True, separators=(",", ":")
|
| 185 |
+
).encode("utf-8")
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
def sha256_bytes(value: bytes) -> str:
|
| 189 |
+
return hashlib.sha256(value).hexdigest()
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def sha256_file(path: pathlib.Path) -> str:
|
| 193 |
+
digest = hashlib.sha256()
|
| 194 |
+
with path.open("rb") as stream:
|
| 195 |
+
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
|
| 196 |
+
digest.update(chunk)
|
| 197 |
+
return digest.hexdigest()
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
def _receipted(value: Mapping[str, Any], field: str) -> dict[str, Any]:
|
| 201 |
+
result = dict(value)
|
| 202 |
+
result[field] = sha256_bytes(canonical_bytes(value))
|
| 203 |
+
return result
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
def _is_sha256(value: Any) -> bool:
|
| 207 |
+
return isinstance(value, str) and _SHA256_RE.fullmatch(value) is not None
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
def _parse_utc(value: Any) -> dt.datetime | None:
|
| 211 |
+
if not isinstance(value, str) or not value.strip():
|
| 212 |
+
return None
|
| 213 |
+
try:
|
| 214 |
+
parsed = dt.datetime.fromisoformat(value.replace("Z", "+00:00"))
|
| 215 |
+
except ValueError:
|
| 216 |
+
return None
|
| 217 |
+
if parsed.tzinfo is None or parsed.utcoffset() is None:
|
| 218 |
+
return None
|
| 219 |
+
return parsed.astimezone(dt.timezone.utc)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
def _format_utc(value: dt.datetime) -> str:
|
| 223 |
+
return value.astimezone(dt.timezone.utc).isoformat().replace("+00:00", "Z")
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def _unique_reasons(reasons: Iterable[str]) -> list[str]:
|
| 227 |
+
return sorted(set(reasons))
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
def _safe_evidence_path(root: pathlib.Path, raw_path: Any) -> pathlib.Path | None:
|
| 231 |
+
if not isinstance(raw_path, str) or not raw_path or "\x00" in raw_path:
|
| 232 |
+
return None
|
| 233 |
+
relative = pathlib.Path(raw_path)
|
| 234 |
+
if relative.is_absolute():
|
| 235 |
+
return None
|
| 236 |
+
candidate = (root / relative).resolve()
|
| 237 |
+
try:
|
| 238 |
+
candidate.relative_to(root)
|
| 239 |
+
except ValueError:
|
| 240 |
+
return None
|
| 241 |
+
return candidate
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def _trusted_signer(
|
| 245 |
+
policy: AdmissionPolicy, key_id: Any
|
| 246 |
+
) -> TrustedEvidenceSigner | None:
|
| 247 |
+
if not isinstance(key_id, str):
|
| 248 |
+
return None
|
| 249 |
+
return next(
|
| 250 |
+
(item for item in policy.trusted_evidence_signers if item.key_id == key_id),
|
| 251 |
+
None,
|
| 252 |
+
)
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
def _signed_payload(envelope: Mapping[str, Any]) -> dict[str, Any]:
|
| 256 |
+
return {
|
| 257 |
+
"schema_version": envelope.get("schema_version"),
|
| 258 |
+
"issuer": envelope.get("issuer"),
|
| 259 |
+
"tool_identity": envelope.get("tool_identity"),
|
| 260 |
+
"issued_at_utc": envelope.get("issued_at_utc"),
|
| 261 |
+
"statement": envelope.get("statement"),
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def _verify_bound_evidence(
|
| 266 |
+
descriptor: Any,
|
| 267 |
+
policy: AdmissionPolicy,
|
| 268 |
+
prefix: str,
|
| 269 |
+
schema: str,
|
| 270 |
+
expected: Mapping[str, Any],
|
| 271 |
+
*,
|
| 272 |
+
exact_statement_fields: bool = True,
|
| 273 |
+
) -> tuple[dict[str, Any], list[str], Mapping[str, Any] | None]:
|
| 274 |
+
observed: dict[str, Any] = {
|
| 275 |
+
"path": None,
|
| 276 |
+
"sha256": None,
|
| 277 |
+
"status": "UNVERIFIED",
|
| 278 |
+
}
|
| 279 |
+
reasons: list[str] = []
|
| 280 |
+
if not isinstance(descriptor, Mapping) or set(descriptor) != {"path", "sha256"}:
|
| 281 |
+
return observed, [f"{prefix}_EVIDENCE_DESCRIPTOR_INVALID"], None
|
| 282 |
+
raw_path = descriptor.get("path")
|
| 283 |
+
declared_sha = descriptor.get("sha256")
|
| 284 |
+
observed["path"] = raw_path if isinstance(raw_path, str) else None
|
| 285 |
+
observed["sha256"] = declared_sha if isinstance(declared_sha, str) else None
|
| 286 |
+
if not _is_sha256(declared_sha):
|
| 287 |
+
reasons.append(f"{prefix}_EVIDENCE_SHA256_INVALID")
|
| 288 |
+
path = _safe_evidence_path(pathlib.Path(policy.evidence_root), raw_path)
|
| 289 |
+
if path is None:
|
| 290 |
+
reasons.append(f"{prefix}_EVIDENCE_PATH_UNSAFE")
|
| 291 |
+
return observed, _unique_reasons(reasons), None
|
| 292 |
+
if not path.is_file():
|
| 293 |
+
reasons.append(f"{prefix}_EVIDENCE_FILE_MISSING")
|
| 294 |
+
return observed, _unique_reasons(reasons), None
|
| 295 |
+
size = path.stat().st_size
|
| 296 |
+
observed["bytes"] = size
|
| 297 |
+
if size > MAX_EVIDENCE_BYTES:
|
| 298 |
+
reasons.append(f"{prefix}_EVIDENCE_FILE_TOO_LARGE")
|
| 299 |
+
return observed, _unique_reasons(reasons), None
|
| 300 |
+
actual_sha = sha256_file(path)
|
| 301 |
+
observed["observed_sha256"] = actual_sha
|
| 302 |
+
if declared_sha != actual_sha:
|
| 303 |
+
reasons.append(f"{prefix}_EVIDENCE_HASH_MISMATCH")
|
| 304 |
+
return observed, _unique_reasons(reasons), None
|
| 305 |
+
try:
|
| 306 |
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
| 307 |
+
except (OSError, UnicodeError, json.JSONDecodeError):
|
| 308 |
+
reasons.append(f"{prefix}_EVIDENCE_JSON_INVALID")
|
| 309 |
+
return observed, _unique_reasons(reasons), None
|
| 310 |
+
if not isinstance(payload, Mapping) or set(payload) != _SIGNED_ENVELOPE_FIELDS:
|
| 311 |
+
reasons.append(f"{prefix}_EVIDENCE_ENVELOPE_INVALID")
|
| 312 |
+
return observed, _unique_reasons(reasons), None
|
| 313 |
+
if payload.get("schema_version") != schema:
|
| 314 |
+
reasons.append(f"{prefix}_EVIDENCE_SCHEMA_MISMATCH")
|
| 315 |
+
statement = payload.get("statement")
|
| 316 |
+
if not isinstance(statement, Mapping):
|
| 317 |
+
reasons.append(f"{prefix}_EVIDENCE_STATEMENT_INVALID")
|
| 318 |
+
statement = None
|
| 319 |
+
else:
|
| 320 |
+
if exact_statement_fields and set(statement) != set(expected):
|
| 321 |
+
reasons.append(f"{prefix}_EVIDENCE_STATEMENT_FIELDS_INVALID")
|
| 322 |
+
for field, expected_value in expected.items():
|
| 323 |
+
if statement.get(field) != expected_value:
|
| 324 |
+
reasons.append(f"{prefix}_EVIDENCE_BINDING_MISMATCH:{field}")
|
| 325 |
+
|
| 326 |
+
issued_at = _parse_utc(payload.get("issued_at_utc"))
|
| 327 |
+
as_of = _parse_utc(policy.as_of_utc)
|
| 328 |
+
if issued_at is None:
|
| 329 |
+
reasons.append(f"{prefix}_EVIDENCE_ISSUED_AT_INVALID")
|
| 330 |
+
elif as_of is not None and issued_at > as_of:
|
| 331 |
+
reasons.append(f"{prefix}_EVIDENCE_ISSUED_IN_FUTURE")
|
| 332 |
+
|
| 333 |
+
signature = payload.get("signature")
|
| 334 |
+
if not isinstance(signature, Mapping) or set(signature) != _SIGNATURE_FIELDS:
|
| 335 |
+
reasons.append(f"{prefix}_EVIDENCE_SIGNATURE_DESCRIPTOR_INVALID")
|
| 336 |
+
else:
|
| 337 |
+
key_id = signature.get("key_id")
|
| 338 |
+
signer = _trusted_signer(policy, key_id)
|
| 339 |
+
if signature.get("algorithm") != SIGNATURE_ALGORITHM:
|
| 340 |
+
reasons.append(f"{prefix}_EVIDENCE_SIGNATURE_ALGORITHM_INVALID")
|
| 341 |
+
if signer is None:
|
| 342 |
+
reasons.append(f"{prefix}_EVIDENCE_SIGNER_NOT_ALLOWLISTED")
|
| 343 |
+
else:
|
| 344 |
+
if payload.get("issuer") != signer.issuer:
|
| 345 |
+
reasons.append(f"{prefix}_EVIDENCE_ISSUER_NOT_ALLOWLISTED")
|
| 346 |
+
if payload.get("tool_identity") != signer.tool_identity:
|
| 347 |
+
reasons.append(f"{prefix}_EVIDENCE_TOOL_NOT_ALLOWLISTED")
|
| 348 |
+
try:
|
| 349 |
+
signature_bytes = base64.b64decode(
|
| 350 |
+
signature.get("value_base64"), validate=True
|
| 351 |
+
)
|
| 352 |
+
except (binascii.Error, TypeError, ValueError):
|
| 353 |
+
reasons.append(f"{prefix}_EVIDENCE_SIGNATURE_ENCODING_INVALID")
|
| 354 |
+
else:
|
| 355 |
+
key_path = _safe_evidence_path(
|
| 356 |
+
pathlib.Path(policy.evidence_root), signer.public_key_path
|
| 357 |
+
)
|
| 358 |
+
try:
|
| 359 |
+
if key_path is None:
|
| 360 |
+
raise ValueError("trusted public key path is unsafe")
|
| 361 |
+
public_key = serialization.load_pem_public_key(key_path.read_bytes())
|
| 362 |
+
if not isinstance(public_key, Ed25519PublicKey):
|
| 363 |
+
raise TypeError("trusted public key is not Ed25519")
|
| 364 |
+
public_key.verify(signature_bytes, canonical_bytes(_signed_payload(payload)))
|
| 365 |
+
except InvalidSignature:
|
| 366 |
+
reasons.append(f"{prefix}_EVIDENCE_SIGNATURE_INVALID")
|
| 367 |
+
except (OSError, TypeError, ValueError):
|
| 368 |
+
reasons.append(f"{prefix}_EVIDENCE_PUBLIC_KEY_VERIFICATION_FAILED")
|
| 369 |
+
if not reasons:
|
| 370 |
+
observed.update(
|
| 371 |
+
{
|
| 372 |
+
"status": "VERIFIED_SIGNED_CONTENT_BINDING",
|
| 373 |
+
"issuer": payload.get("issuer"),
|
| 374 |
+
"tool_identity": payload.get("tool_identity"),
|
| 375 |
+
"key_id": signature.get("key_id") if isinstance(signature, Mapping) else None,
|
| 376 |
+
"statement_sha256": sha256_bytes(canonical_bytes(statement)),
|
| 377 |
+
}
|
| 378 |
+
)
|
| 379 |
+
return observed, _unique_reasons(reasons), statement
|
| 380 |
+
|
| 381 |
+
|
| 382 |
+
def _checked_against_sha256(references: Sequence[str]) -> str:
|
| 383 |
+
return sha256_bytes(canonical_bytes(list(references)))
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
def _protected_eval_set_sha256(values: Iterable[str]) -> str:
|
| 387 |
+
return sha256_bytes(canonical_bytes(sorted(set(values))))
|
| 388 |
+
|
| 389 |
+
|
| 390 |
+
def _verify_contamination_run_receipt(
|
| 391 |
+
statement: Mapping[str, Any] | None,
|
| 392 |
+
*,
|
| 393 |
+
expected_tool_identity: str | None,
|
| 394 |
+
method: Any,
|
| 395 |
+
content_sha256: Any,
|
| 396 |
+
checked_against_sha256: str,
|
| 397 |
+
result: Any,
|
| 398 |
+
) -> list[str]:
|
| 399 |
+
prefix = "CONTAMINATION"
|
| 400 |
+
if not isinstance(statement, Mapping):
|
| 401 |
+
return [f"{prefix}_RUN_RECEIPT_MISSING"]
|
| 402 |
+
required = {
|
| 403 |
+
"result",
|
| 404 |
+
"method",
|
| 405 |
+
"candidate_content_sha256",
|
| 406 |
+
"checked_against_sha256",
|
| 407 |
+
"run_receipt",
|
| 408 |
+
"run_receipt_sha256",
|
| 409 |
+
}
|
| 410 |
+
reasons: list[str] = []
|
| 411 |
+
if set(statement) != required:
|
| 412 |
+
reasons.append(f"{prefix}_EVIDENCE_STATEMENT_FIELDS_INVALID")
|
| 413 |
+
receipt = statement.get("run_receipt")
|
| 414 |
+
if not isinstance(receipt, Mapping) or set(receipt) != _RUN_RECEIPT_FIELDS:
|
| 415 |
+
reasons.append(f"{prefix}_RUN_RECEIPT_INVALID")
|
| 416 |
+
return _unique_reasons(reasons)
|
| 417 |
+
receipt_sha = statement.get("run_receipt_sha256")
|
| 418 |
+
if not _is_sha256(receipt_sha) or receipt_sha != sha256_bytes(canonical_bytes(receipt)):
|
| 419 |
+
reasons.append(f"{prefix}_RUN_RECEIPT_HASH_MISMATCH")
|
| 420 |
+
expected_receipt = {
|
| 421 |
+
"tool_identity": expected_tool_identity,
|
| 422 |
+
"method": method,
|
| 423 |
+
"candidate_content_sha256": content_sha256,
|
| 424 |
+
"checked_against_sha256": checked_against_sha256,
|
| 425 |
+
"result": result,
|
| 426 |
+
}
|
| 427 |
+
for field, expected_value in expected_receipt.items():
|
| 428 |
+
if receipt.get(field) != expected_value:
|
| 429 |
+
reasons.append(f"{prefix}_RUN_RECEIPT_BINDING_MISMATCH:{field}")
|
| 430 |
+
if not isinstance(receipt.get("run_id"), str) or not receipt.get("run_id"):
|
| 431 |
+
reasons.append(f"{prefix}_RUN_RECEIPT_RUN_ID_INVALID")
|
| 432 |
+
if _parse_utc(receipt.get("completed_at_utc")) is None:
|
| 433 |
+
reasons.append(f"{prefix}_RUN_RECEIPT_COMPLETED_AT_INVALID")
|
| 434 |
+
return _unique_reasons(reasons)
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
def _load_split_ledger(
|
| 438 |
+
policy: AdmissionPolicy,
|
| 439 |
+
) -> tuple[dict[str, str], dict[str, Any], list[str]]:
|
| 440 |
+
descriptor = policy.split_ledger_evidence
|
| 441 |
+
if descriptor is None:
|
| 442 |
+
return {}, {"status": "MISSING"}, ["SPLIT_LEDGER_REQUIRED"]
|
| 443 |
+
observed, reasons, statement = _verify_bound_evidence(
|
| 444 |
+
descriptor,
|
| 445 |
+
policy,
|
| 446 |
+
"SPLIT_LEDGER",
|
| 447 |
+
SPLIT_LEDGER_SCHEMA,
|
| 448 |
+
{},
|
| 449 |
+
exact_statement_fields=False,
|
| 450 |
+
)
|
| 451 |
+
if not isinstance(statement, Mapping):
|
| 452 |
+
return {}, observed, _unique_reasons([*reasons, "SPLIT_LEDGER_STATEMENT_INVALID"])
|
| 453 |
+
expected_fields = {
|
| 454 |
+
"ledger_id",
|
| 455 |
+
"as_of_utc",
|
| 456 |
+
"previous_ledger_sha256",
|
| 457 |
+
"protected_eval_set_sha256",
|
| 458 |
+
"entries",
|
| 459 |
+
}
|
| 460 |
+
if set(statement) != expected_fields:
|
| 461 |
+
reasons.append("SPLIT_LEDGER_STATEMENT_FIELDS_INVALID")
|
| 462 |
+
if not isinstance(statement.get("ledger_id"), str) or not statement.get("ledger_id"):
|
| 463 |
+
reasons.append("SPLIT_LEDGER_ID_INVALID")
|
| 464 |
+
ledger_as_of = _parse_utc(statement.get("as_of_utc"))
|
| 465 |
+
policy_as_of = _parse_utc(policy.as_of_utc)
|
| 466 |
+
if ledger_as_of is None:
|
| 467 |
+
reasons.append("SPLIT_LEDGER_AS_OF_INVALID")
|
| 468 |
+
elif policy_as_of is not None and ledger_as_of > policy_as_of:
|
| 469 |
+
reasons.append("SPLIT_LEDGER_AS_OF_IN_FUTURE")
|
| 470 |
+
previous = statement.get("previous_ledger_sha256")
|
| 471 |
+
if previous is not None and not _is_sha256(previous):
|
| 472 |
+
reasons.append("SPLIT_LEDGER_PREVIOUS_HASH_INVALID")
|
| 473 |
+
if statement.get("protected_eval_set_sha256") != _protected_eval_set_sha256(
|
| 474 |
+
policy.protected_eval_content_sha256
|
| 475 |
+
):
|
| 476 |
+
reasons.append("SPLIT_LEDGER_PROTECTED_EVAL_BINDING_MISMATCH")
|
| 477 |
+
raw_entries = statement.get("entries")
|
| 478 |
+
ledger: dict[str, str] = {}
|
| 479 |
+
normalized: list[dict[str, str]] = []
|
| 480 |
+
if not isinstance(raw_entries, list):
|
| 481 |
+
reasons.append("SPLIT_LEDGER_ENTRIES_INVALID")
|
| 482 |
+
else:
|
| 483 |
+
for entry in raw_entries:
|
| 484 |
+
if (
|
| 485 |
+
not isinstance(entry, Mapping)
|
| 486 |
+
or set(entry) != {"content_sha256", "split"}
|
| 487 |
+
or not _is_sha256(entry.get("content_sha256"))
|
| 488 |
+
or entry.get("split") not in SPLITS
|
| 489 |
+
):
|
| 490 |
+
reasons.append("SPLIT_LEDGER_ENTRY_INVALID")
|
| 491 |
+
continue
|
| 492 |
+
content_sha = str(entry["content_sha256"])
|
| 493 |
+
split = str(entry["split"])
|
| 494 |
+
if content_sha in ledger:
|
| 495 |
+
reasons.append(
|
| 496 |
+
"SPLIT_LEDGER_CONFLICTING_ENTRY"
|
| 497 |
+
if ledger[content_sha] != split
|
| 498 |
+
else "SPLIT_LEDGER_DUPLICATE_ENTRY"
|
| 499 |
+
)
|
| 500 |
+
else:
|
| 501 |
+
ledger[content_sha] = split
|
| 502 |
+
normalized.append({"content_sha256": content_sha, "split": split})
|
| 503 |
+
expected_order = sorted(
|
| 504 |
+
normalized, key=lambda item: (item["content_sha256"], item["split"])
|
| 505 |
+
)
|
| 506 |
+
if normalized != expected_order:
|
| 507 |
+
reasons.append("SPLIT_LEDGER_NOT_DETERMINISTIC_ORDER")
|
| 508 |
+
reasons = _unique_reasons(reasons)
|
| 509 |
+
if reasons:
|
| 510 |
+
observed["status"] = "UNVERIFIED"
|
| 511 |
+
return {}, observed, reasons
|
| 512 |
+
observed.update(
|
| 513 |
+
{
|
| 514 |
+
"status": "VERIFIED_SIGNED_FROZEN_LEDGER",
|
| 515 |
+
"ledger_id": statement.get("ledger_id"),
|
| 516 |
+
"as_of_utc": statement.get("as_of_utc"),
|
| 517 |
+
"entry_count": len(ledger),
|
| 518 |
+
}
|
| 519 |
+
)
|
| 520 |
+
return ledger, observed, []
|
| 521 |
+
|
| 522 |
+
|
| 523 |
+
def _uri_is_explicit(value: Any) -> bool:
|
| 524 |
+
if not isinstance(value, str) or len(value) > 2048:
|
| 525 |
+
return False
|
| 526 |
+
parsed = urlsplit(value)
|
| 527 |
+
return bool(parsed.scheme and (parsed.netloc or parsed.path) and not parsed.username)
|
| 528 |
+
|
| 529 |
+
|
| 530 |
+
def _validate_row(raw: Any, index: int, policy: AdmissionPolicy) -> dict[str, Any]:
|
| 531 |
+
reasons: list[str] = []
|
| 532 |
+
candidate_sha = sha256_bytes(canonical_bytes(raw))
|
| 533 |
+
if not isinstance(raw, Mapping):
|
| 534 |
+
return {
|
| 535 |
+
"schema_version": DECISION_SCHEMA,
|
| 536 |
+
"input_index": index,
|
| 537 |
+
"candidate_row_sha256": candidate_sha,
|
| 538 |
+
"node_id": None,
|
| 539 |
+
"content_sha256": None,
|
| 540 |
+
"split": None,
|
| 541 |
+
"dedup_group": None,
|
| 542 |
+
"source": {"status": "UNVERIFIED"},
|
| 543 |
+
"rights": {"status": "UNVERIFIED"},
|
| 544 |
+
"freshness": {"state": "UNKNOWN"},
|
| 545 |
+
"contamination": {"observed_result": "NOT_ESTABLISHED"},
|
| 546 |
+
"reason_codes": ["ROW_NOT_OBJECT"],
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
row_bytes = len(canonical_bytes(raw))
|
| 550 |
+
if row_bytes > MAX_ROW_BYTES:
|
| 551 |
+
reasons.append("ROW_TOO_LARGE")
|
| 552 |
+
missing = sorted(_ROW_FIELDS - set(raw))
|
| 553 |
+
extra = sorted(set(raw) - _ROW_FIELDS)
|
| 554 |
+
if missing:
|
| 555 |
+
reasons.append("ROW_REQUIRED_FIELDS_MISSING")
|
| 556 |
+
if extra:
|
| 557 |
+
reasons.append("ROW_UNRECOGNIZED_FIELDS")
|
| 558 |
+
if raw.get("schema_version") != CANDIDATE_SCHEMA:
|
| 559 |
+
reasons.append("ROW_SCHEMA_MISMATCH")
|
| 560 |
+
|
| 561 |
+
node_id = raw.get("node_id")
|
| 562 |
+
if not isinstance(node_id, str) or _NODE_ID_RE.fullmatch(node_id) is None:
|
| 563 |
+
reasons.append("NODE_ID_INVALID")
|
| 564 |
+
node_id = node_id if isinstance(node_id, str) else None
|
| 565 |
+
|
| 566 |
+
content = raw.get("content")
|
| 567 |
+
if not isinstance(content, str) or not content:
|
| 568 |
+
reasons.append("CONTENT_MISSING")
|
| 569 |
+
content_bytes = b""
|
| 570 |
+
else:
|
| 571 |
+
content_bytes = content.encode("utf-8")
|
| 572 |
+
if len(content_bytes) > MAX_CONTENT_BYTES:
|
| 573 |
+
reasons.append("CONTENT_TOO_LARGE")
|
| 574 |
+
declared_content_sha = raw.get("content_sha256")
|
| 575 |
+
if not _is_sha256(declared_content_sha):
|
| 576 |
+
reasons.append("CONTENT_SHA256_INVALID")
|
| 577 |
+
content_sha = declared_content_sha if isinstance(declared_content_sha, str) else None
|
| 578 |
+
else:
|
| 579 |
+
content_sha = declared_content_sha
|
| 580 |
+
if not isinstance(content, str) or sha256_bytes(content_bytes) != content_sha:
|
| 581 |
+
reasons.append("CONTENT_HASH_MISMATCH")
|
| 582 |
+
|
| 583 |
+
split = raw.get("split")
|
| 584 |
+
if split not in SPLITS:
|
| 585 |
+
reasons.append("SPLIT_INVALID")
|
| 586 |
+
split = split if isinstance(split, str) else None
|
| 587 |
+
|
| 588 |
+
source_raw = raw.get("source")
|
| 589 |
+
source_result: dict[str, Any] = {"status": "UNVERIFIED"}
|
| 590 |
+
freshness: dict[str, Any] = {
|
| 591 |
+
"source_timestamp_utc": None,
|
| 592 |
+
"as_of_utc": policy.as_of_utc,
|
| 593 |
+
"max_age_days": policy.max_age_days,
|
| 594 |
+
"age_seconds": None,
|
| 595 |
+
"state": "UNKNOWN",
|
| 596 |
+
}
|
| 597 |
+
if not isinstance(source_raw, Mapping):
|
| 598 |
+
reasons.append("SOURCE_INVALID")
|
| 599 |
+
else:
|
| 600 |
+
if set(source_raw) != _SOURCE_FIELDS:
|
| 601 |
+
reasons.append("SOURCE_FIELDS_INVALID")
|
| 602 |
+
uri = source_raw.get("uri")
|
| 603 |
+
revision = source_raw.get("revision")
|
| 604 |
+
timestamp = source_raw.get("timestamp_utc")
|
| 605 |
+
if not _uri_is_explicit(uri):
|
| 606 |
+
reasons.append("SOURCE_URI_INVALID")
|
| 607 |
+
if not isinstance(revision, str) or _REVISION_RE.fullmatch(revision) is None:
|
| 608 |
+
reasons.append("SOURCE_IMMUTABLE_REVISION_REQUIRED")
|
| 609 |
+
timestamp_value = _parse_utc(timestamp)
|
| 610 |
+
if timestamp_value is None:
|
| 611 |
+
reasons.append("SOURCE_TIMESTAMP_INVALID")
|
| 612 |
+
else:
|
| 613 |
+
as_of_value = _parse_utc(policy.as_of_utc)
|
| 614 |
+
assert as_of_value is not None
|
| 615 |
+
age_seconds = int((as_of_value - timestamp_value).total_seconds())
|
| 616 |
+
freshness.update(
|
| 617 |
+
{
|
| 618 |
+
"source_timestamp_utc": _format_utc(timestamp_value),
|
| 619 |
+
"age_seconds": age_seconds,
|
| 620 |
+
}
|
| 621 |
+
)
|
| 622 |
+
if age_seconds < 0:
|
| 623 |
+
freshness["state"] = "FUTURE"
|
| 624 |
+
reasons.append("SOURCE_TIMESTAMP_IN_FUTURE")
|
| 625 |
+
elif age_seconds > policy.max_age_days * 86_400:
|
| 626 |
+
freshness["state"] = "STALE"
|
| 627 |
+
reasons.append("SOURCE_STALE")
|
| 628 |
+
else:
|
| 629 |
+
freshness["state"] = "FRESH"
|
| 630 |
+
source_evidence, source_reasons, _ = _verify_bound_evidence(
|
| 631 |
+
source_raw.get("evidence"),
|
| 632 |
+
policy,
|
| 633 |
+
"SOURCE",
|
| 634 |
+
SOURCE_EVIDENCE_SCHEMA,
|
| 635 |
+
{
|
| 636 |
+
"candidate_content_sha256": declared_content_sha,
|
| 637 |
+
"source_uri": uri,
|
| 638 |
+
"source_revision": revision,
|
| 639 |
+
},
|
| 640 |
+
)
|
| 641 |
+
reasons.extend(source_reasons)
|
| 642 |
+
source_shape_ok = (
|
| 643 |
+
_uri_is_explicit(uri)
|
| 644 |
+
and isinstance(revision, str)
|
| 645 |
+
and _REVISION_RE.fullmatch(revision) is not None
|
| 646 |
+
)
|
| 647 |
+
source_result = {
|
| 648 |
+
"uri": uri if isinstance(uri, str) else None,
|
| 649 |
+
"revision": revision if isinstance(revision, str) else None,
|
| 650 |
+
"revision_state": (
|
| 651 |
+
"PINNED_IDENTIFIER_WITH_SIGNED_EVIDENCE"
|
| 652 |
+
if not source_reasons
|
| 653 |
+
and source_shape_ok
|
| 654 |
+
else "UNVERIFIED"
|
| 655 |
+
),
|
| 656 |
+
"evidence": source_evidence,
|
| 657 |
+
"status": (
|
| 658 |
+
"VERIFIED_SIGNED_BINDING"
|
| 659 |
+
if not source_reasons and source_shape_ok
|
| 660 |
+
else "UNVERIFIED"
|
| 661 |
+
),
|
| 662 |
+
}
|
| 663 |
+
|
| 664 |
+
rights_raw = raw.get("rights")
|
| 665 |
+
rights_result: dict[str, Any] = {"status": "UNVERIFIED"}
|
| 666 |
+
if not isinstance(rights_raw, Mapping):
|
| 667 |
+
reasons.append("RIGHTS_INVALID")
|
| 668 |
+
else:
|
| 669 |
+
if set(rights_raw) != _RIGHTS_FIELDS:
|
| 670 |
+
reasons.append("RIGHTS_FIELDS_INVALID")
|
| 671 |
+
basis = rights_raw.get("basis")
|
| 672 |
+
license_id = rights_raw.get("license")
|
| 673 |
+
if basis not in policy.allowed_rights_bases:
|
| 674 |
+
reasons.append("RIGHTS_BASIS_NOT_ALLOWED")
|
| 675 |
+
if license_id not in policy.allowed_licenses:
|
| 676 |
+
reasons.append("LICENSE_NOT_ALLOWED")
|
| 677 |
+
revision = source_raw.get("revision") if isinstance(source_raw, Mapping) else None
|
| 678 |
+
source_uri = source_raw.get("uri") if isinstance(source_raw, Mapping) else None
|
| 679 |
+
rights_evidence, rights_reasons, _ = _verify_bound_evidence(
|
| 680 |
+
rights_raw.get("evidence"),
|
| 681 |
+
policy,
|
| 682 |
+
"RIGHTS",
|
| 683 |
+
RIGHTS_EVIDENCE_SCHEMA,
|
| 684 |
+
{
|
| 685 |
+
"candidate_content_sha256": declared_content_sha,
|
| 686 |
+
"source_uri": source_uri,
|
| 687 |
+
"source_revision": revision,
|
| 688 |
+
"basis": basis,
|
| 689 |
+
"license": license_id,
|
| 690 |
+
},
|
| 691 |
+
)
|
| 692 |
+
reasons.extend(rights_reasons)
|
| 693 |
+
rights_result = {
|
| 694 |
+
"basis": basis if isinstance(basis, str) else None,
|
| 695 |
+
"license": license_id if isinstance(license_id, str) else None,
|
| 696 |
+
"evidence": rights_evidence,
|
| 697 |
+
"status": (
|
| 698 |
+
"VERIFIED_SIGNED_CONTENT_RIGHTS_BINDING"
|
| 699 |
+
if not rights_reasons
|
| 700 |
+
and basis in policy.allowed_rights_bases
|
| 701 |
+
and license_id in policy.allowed_licenses
|
| 702 |
+
else "UNVERIFIED"
|
| 703 |
+
),
|
| 704 |
+
}
|
| 705 |
+
|
| 706 |
+
contamination_raw = raw.get("contamination")
|
| 707 |
+
contamination_result: dict[str, Any] = {
|
| 708 |
+
"declared_result": None,
|
| 709 |
+
"observed_result": "NOT_ESTABLISHED",
|
| 710 |
+
"method": None,
|
| 711 |
+
"checked_against": [],
|
| 712 |
+
"evidence": {"status": "UNVERIFIED"},
|
| 713 |
+
}
|
| 714 |
+
if not isinstance(contamination_raw, Mapping):
|
| 715 |
+
reasons.append("CONTAMINATION_INVALID")
|
| 716 |
+
else:
|
| 717 |
+
if set(contamination_raw) != _CONTAMINATION_FIELDS:
|
| 718 |
+
reasons.append("CONTAMINATION_FIELDS_INVALID")
|
| 719 |
+
declared_result = contamination_raw.get("result")
|
| 720 |
+
method = contamination_raw.get("method")
|
| 721 |
+
references = contamination_raw.get("checked_against")
|
| 722 |
+
if declared_result != "CLEAR":
|
| 723 |
+
reasons.append(
|
| 724 |
+
"CONTAMINATION_DETECTED"
|
| 725 |
+
if declared_result == "DETECTED"
|
| 726 |
+
else "CONTAMINATION_NOT_CLEARED"
|
| 727 |
+
)
|
| 728 |
+
if not isinstance(method, str) or _METHOD_RE.fullmatch(method) is None:
|
| 729 |
+
reasons.append("CONTAMINATION_METHOD_INVALID")
|
| 730 |
+
references_valid = (
|
| 731 |
+
isinstance(references, list)
|
| 732 |
+
and 0 < len(references) <= MAX_REFERENCES
|
| 733 |
+
and len(references) == len(set(references))
|
| 734 |
+
and all(
|
| 735 |
+
isinstance(item, str) and _REFERENCE_RE.fullmatch(item) is not None
|
| 736 |
+
for item in references
|
| 737 |
+
)
|
| 738 |
+
)
|
| 739 |
+
if not references_valid:
|
| 740 |
+
reasons.append("CONTAMINATION_REFERENCE_SET_INVALID")
|
| 741 |
+
checked_against = list(references) if references_valid else []
|
| 742 |
+
reference_digest = _checked_against_sha256(checked_against)
|
| 743 |
+
contamination_evidence, contamination_reasons, contamination_statement = _verify_bound_evidence(
|
| 744 |
+
contamination_raw.get("evidence"),
|
| 745 |
+
policy,
|
| 746 |
+
"CONTAMINATION",
|
| 747 |
+
CONTAMINATION_EVIDENCE_SCHEMA,
|
| 748 |
+
{
|
| 749 |
+
"result": declared_result,
|
| 750 |
+
"method": method,
|
| 751 |
+
"candidate_content_sha256": declared_content_sha,
|
| 752 |
+
"checked_against_sha256": reference_digest,
|
| 753 |
+
},
|
| 754 |
+
exact_statement_fields=False,
|
| 755 |
+
)
|
| 756 |
+
contamination_reasons.extend(
|
| 757 |
+
_verify_contamination_run_receipt(
|
| 758 |
+
contamination_statement,
|
| 759 |
+
expected_tool_identity=(
|
| 760 |
+
contamination_evidence.get("tool_identity")
|
| 761 |
+
if isinstance(contamination_evidence, Mapping)
|
| 762 |
+
else None
|
| 763 |
+
),
|
| 764 |
+
method=method,
|
| 765 |
+
content_sha256=declared_content_sha,
|
| 766 |
+
checked_against_sha256=reference_digest,
|
| 767 |
+
result=declared_result,
|
| 768 |
+
)
|
| 769 |
+
)
|
| 770 |
+
contamination_reasons = _unique_reasons(contamination_reasons)
|
| 771 |
+
if contamination_reasons:
|
| 772 |
+
contamination_evidence["status"] = "UNVERIFIED"
|
| 773 |
+
reasons.extend(contamination_reasons)
|
| 774 |
+
contamination_result = {
|
| 775 |
+
"declared_result": declared_result if isinstance(declared_result, str) else None,
|
| 776 |
+
"observed_result": (
|
| 777 |
+
"CLEAR_WITH_SIGNED_RUN_RECEIPT"
|
| 778 |
+
if declared_result == "CLEAR"
|
| 779 |
+
and not contamination_reasons
|
| 780 |
+
and isinstance(method, str)
|
| 781 |
+
and _METHOD_RE.fullmatch(method) is not None
|
| 782 |
+
and references_valid
|
| 783 |
+
else "NOT_ESTABLISHED"
|
| 784 |
+
),
|
| 785 |
+
"method": method if isinstance(method, str) else None,
|
| 786 |
+
"checked_against": checked_against,
|
| 787 |
+
"evidence": contamination_evidence,
|
| 788 |
+
}
|
| 789 |
+
|
| 790 |
+
if (
|
| 791 |
+
split == "TRAIN"
|
| 792 |
+
and _is_sha256(content_sha)
|
| 793 |
+
and content_sha in policy.protected_eval_content_sha256
|
| 794 |
+
):
|
| 795 |
+
reasons.append("PROTECTED_EVAL_CONTENT_IN_TRAIN")
|
| 796 |
+
contamination_result["observed_result"] = "PROTECTED_EVAL_MATCH"
|
| 797 |
+
elif (
|
| 798 |
+
split == "EVAL"
|
| 799 |
+
and _is_sha256(content_sha)
|
| 800 |
+
and content_sha in policy.protected_eval_content_sha256
|
| 801 |
+
):
|
| 802 |
+
contamination_result["observed_result"] = "PROTECTED_EVAL_MEMBER"
|
| 803 |
+
|
| 804 |
+
return {
|
| 805 |
+
"schema_version": DECISION_SCHEMA,
|
| 806 |
+
"input_index": index,
|
| 807 |
+
"candidate_row_sha256": candidate_sha,
|
| 808 |
+
"node_id": node_id,
|
| 809 |
+
"content": content if isinstance(content, str) else None,
|
| 810 |
+
"content_sha256": content_sha,
|
| 811 |
+
"split": split,
|
| 812 |
+
"dedup_group": f"sha256:{content_sha}" if _is_sha256(content_sha) else None,
|
| 813 |
+
"canonical_node_id": node_id if isinstance(node_id, str) else None,
|
| 814 |
+
"source": source_result,
|
| 815 |
+
"rights": rights_result,
|
| 816 |
+
"freshness": freshness,
|
| 817 |
+
"contamination": contamination_result,
|
| 818 |
+
"reason_codes": _unique_reasons(reasons),
|
| 819 |
+
}
|
| 820 |
+
|
| 821 |
+
|
| 822 |
+
def _append_reason(record: dict[str, Any], reason: str) -> None:
|
| 823 |
+
record["reason_codes"] = _unique_reasons([*record["reason_codes"], reason])
|
| 824 |
+
|
| 825 |
+
|
| 826 |
+
def _finalize_record(record: Mapping[str, Any]) -> dict[str, Any]:
|
| 827 |
+
body = dict(record)
|
| 828 |
+
reasons = list(body.pop("reason_codes", []))
|
| 829 |
+
admitted = not reasons
|
| 830 |
+
split = body.get("split")
|
| 831 |
+
body.update(
|
| 832 |
+
{
|
| 833 |
+
"canonical_status": "CANONICAL" if admitted else "QUARANTINED",
|
| 834 |
+
"admission_decision": (
|
| 835 |
+
f"ADMIT_{split}" if admitted and split in SPLITS else "QUARANTINE"
|
| 836 |
+
),
|
| 837 |
+
"training_eligible": admitted and split == "TRAIN",
|
| 838 |
+
"evaluation_eligible": admitted and split == "EVAL",
|
| 839 |
+
"reason_codes": reasons,
|
| 840 |
+
}
|
| 841 |
+
)
|
| 842 |
+
if not admitted:
|
| 843 |
+
body.pop("content", None)
|
| 844 |
+
body["content_included"] = False
|
| 845 |
+
else:
|
| 846 |
+
body["content_included"] = True
|
| 847 |
+
return _receipted(body, "decision_receipt_sha256")
|
| 848 |
+
|
| 849 |
+
|
| 850 |
+
def admit_rows(rows: Sequence[Any], policy: AdmissionPolicy) -> dict[str, Any]:
|
| 851 |
+
"""Evaluate a bounded in-memory batch and return a receipted machine report."""
|
| 852 |
+
|
| 853 |
+
if len(rows) > MAX_ROWS:
|
| 854 |
+
raise AdmissionInputError("INPUT_ROW_LIMIT_EXCEEDED")
|
| 855 |
+
drafts = [_validate_row(raw, index, policy) for index, raw in enumerate(rows)]
|
| 856 |
+
prior_split_ledger, split_ledger_observed, split_ledger_reasons = _load_split_ledger(
|
| 857 |
+
policy
|
| 858 |
+
)
|
| 859 |
+
|
| 860 |
+
for record in drafts:
|
| 861 |
+
split = record.get("split")
|
| 862 |
+
content_sha = record.get("content_sha256")
|
| 863 |
+
if split == "TRAIN":
|
| 864 |
+
if not policy.protected_eval_content_sha256:
|
| 865 |
+
_append_reason(record, "FROZEN_EVAL_HASHES_REQUIRED_FOR_TRAIN")
|
| 866 |
+
for reason in split_ledger_reasons:
|
| 867 |
+
_append_reason(record, reason)
|
| 868 |
+
if not split_ledger_reasons and _is_sha256(content_sha):
|
| 869 |
+
prior_split = prior_split_ledger.get(str(content_sha))
|
| 870 |
+
if prior_split is not None:
|
| 871 |
+
_append_reason(
|
| 872 |
+
record,
|
| 873 |
+
"CROSS_RUN_SPLIT_CONFLICT"
|
| 874 |
+
if prior_split != split
|
| 875 |
+
else "CROSS_RUN_CONTENT_REUSE",
|
| 876 |
+
)
|
| 877 |
+
record["contamination"]["observed_result"] = (
|
| 878 |
+
"CROSS_RUN_SPLIT_MATCH"
|
| 879 |
+
if prior_split != split
|
| 880 |
+
else "PRIOR_RUN_CONTENT_MATCH"
|
| 881 |
+
)
|
| 882 |
+
|
| 883 |
+
by_node: dict[str, list[dict[str, Any]]] = collections.defaultdict(list)
|
| 884 |
+
by_content: dict[str, list[dict[str, Any]]] = collections.defaultdict(list)
|
| 885 |
+
for record in drafts:
|
| 886 |
+
if isinstance(record.get("node_id"), str):
|
| 887 |
+
by_node[record["node_id"]].append(record)
|
| 888 |
+
if _is_sha256(record.get("content_sha256")):
|
| 889 |
+
by_content[record["content_sha256"]].append(record)
|
| 890 |
+
|
| 891 |
+
for group in by_node.values():
|
| 892 |
+
if len(group) > 1:
|
| 893 |
+
for record in group:
|
| 894 |
+
_append_reason(record, "DUPLICATE_NODE_ID")
|
| 895 |
+
|
| 896 |
+
for content_sha, group in by_content.items():
|
| 897 |
+
if len(group) < 2:
|
| 898 |
+
continue
|
| 899 |
+
splits = {record.get("split") for record in group if record.get("split") in SPLITS}
|
| 900 |
+
canonical = min(
|
| 901 |
+
group,
|
| 902 |
+
key=lambda record: (
|
| 903 |
+
str(record.get("node_id") or "~"),
|
| 904 |
+
str(record.get("candidate_row_sha256") or "~"),
|
| 905 |
+
int(record.get("input_index") or 0),
|
| 906 |
+
),
|
| 907 |
+
)
|
| 908 |
+
canonical_node_id = canonical.get("node_id")
|
| 909 |
+
for record in group:
|
| 910 |
+
record["canonical_node_id"] = canonical_node_id
|
| 911 |
+
if len(splits) > 1:
|
| 912 |
+
for record in group:
|
| 913 |
+
_append_reason(record, "DEDUP_GROUP_SPLIT_CONFLICT")
|
| 914 |
+
record["contamination"]["observed_result"] = "CROSS_SPLIT_CONTENT_MATCH"
|
| 915 |
+
else:
|
| 916 |
+
for record in group:
|
| 917 |
+
if record is not canonical:
|
| 918 |
+
_append_reason(record, "DUPLICATE_CONTENT")
|
| 919 |
+
|
| 920 |
+
decisions = [_finalize_record(record) for record in drafts]
|
| 921 |
+
reason_counts: collections.Counter[str] = collections.Counter()
|
| 922 |
+
for decision in decisions:
|
| 923 |
+
reason_counts.update(decision["reason_codes"])
|
| 924 |
+
train_count = sum(item["admission_decision"] == "ADMIT_TRAIN" for item in decisions)
|
| 925 |
+
eval_count = sum(item["admission_decision"] == "ADMIT_EVAL" for item in decisions)
|
| 926 |
+
quarantine_count = sum(item["admission_decision"] == "QUARANTINE" for item in decisions)
|
| 927 |
+
if not decisions:
|
| 928 |
+
state = "EMPTY_INPUT"
|
| 929 |
+
elif quarantine_count == len(decisions):
|
| 930 |
+
state = "ALL_QUARANTINED"
|
| 931 |
+
elif quarantine_count:
|
| 932 |
+
state = "COMPLETE_WITH_QUARANTINE"
|
| 933 |
+
else:
|
| 934 |
+
state = "ADMISSION_COMPLETE"
|
| 935 |
+
if split_ledger_reasons:
|
| 936 |
+
next_split_ledger: dict[str, Any] = {
|
| 937 |
+
"state": "BLOCKED_INVALID_OR_MISSING_PRIOR_LEDGER",
|
| 938 |
+
"reason_codes": split_ledger_reasons,
|
| 939 |
+
}
|
| 940 |
+
else:
|
| 941 |
+
next_entries = dict(prior_split_ledger)
|
| 942 |
+
for decision in decisions:
|
| 943 |
+
if decision.get("admission_decision") in {"ADMIT_TRAIN", "ADMIT_EVAL"}:
|
| 944 |
+
next_entries[str(decision["content_sha256"])] = str(decision["split"])
|
| 945 |
+
next_split_ledger = {
|
| 946 |
+
"state": "UNSIGNED_CANDIDATE_SIGNATURE_REQUIRED_BEFORE_REUSE",
|
| 947 |
+
"schema_version": SPLIT_LEDGER_SCHEMA,
|
| 948 |
+
"previous_ledger_evidence_sha256": (
|
| 949 |
+
policy.split_ledger_evidence.get("sha256")
|
| 950 |
+
if isinstance(policy.split_ledger_evidence, Mapping)
|
| 951 |
+
else None
|
| 952 |
+
),
|
| 953 |
+
"protected_eval_set_sha256": _protected_eval_set_sha256(
|
| 954 |
+
policy.protected_eval_content_sha256
|
| 955 |
+
),
|
| 956 |
+
"entries": [
|
| 957 |
+
{"content_sha256": content_sha, "split": split}
|
| 958 |
+
for content_sha, split in sorted(next_entries.items())
|
| 959 |
+
],
|
| 960 |
+
}
|
| 961 |
+
next_split_ledger["entries_sha256"] = sha256_bytes(
|
| 962 |
+
canonical_bytes(next_split_ledger["entries"])
|
| 963 |
+
)
|
| 964 |
+
body = {
|
| 965 |
+
"schema_version": REPORT_SCHEMA,
|
| 966 |
+
"state": state,
|
| 967 |
+
"policy": {
|
| 968 |
+
"as_of_utc": policy.as_of_utc,
|
| 969 |
+
"max_age_days": policy.max_age_days,
|
| 970 |
+
"allowed_rights_bases": list(policy.allowed_rights_bases),
|
| 971 |
+
"allowed_licenses": list(policy.allowed_licenses),
|
| 972 |
+
"protected_eval_hash_count": len(policy.protected_eval_content_sha256),
|
| 973 |
+
"trusted_evidence_signer_count": len(policy.trusted_evidence_signers),
|
| 974 |
+
"bounds": {
|
| 975 |
+
"max_input_bytes": MAX_INPUT_BYTES,
|
| 976 |
+
"max_rows": MAX_ROWS,
|
| 977 |
+
"max_row_bytes": MAX_ROW_BYTES,
|
| 978 |
+
"max_content_bytes": MAX_CONTENT_BYTES,
|
| 979 |
+
"max_evidence_bytes": MAX_EVIDENCE_BYTES,
|
| 980 |
+
},
|
| 981 |
+
},
|
| 982 |
+
"summary": {
|
| 983 |
+
"observed_rows": len(decisions),
|
| 984 |
+
"admitted_train_rows": train_count,
|
| 985 |
+
"admitted_eval_rows": eval_count,
|
| 986 |
+
"quarantined_rows": quarantine_count,
|
| 987 |
+
"dedup_group_count": len(by_content),
|
| 988 |
+
"reason_counts": dict(sorted(reason_counts.items())),
|
| 989 |
+
},
|
| 990 |
+
"training_input_state": (
|
| 991 |
+
"ADMITTED_ROWS_PRESENT_NOT_TRAINING_AUTHORIZATION"
|
| 992 |
+
if train_count
|
| 993 |
+
else "BLOCKED_ZERO_ADMITTED_TRAIN_ROWS"
|
| 994 |
+
),
|
| 995 |
+
"split_ledger": {
|
| 996 |
+
"observed": split_ledger_observed,
|
| 997 |
+
"reason_codes": split_ledger_reasons,
|
| 998 |
+
"next_unsigned_candidate": next_split_ledger,
|
| 999 |
+
},
|
| 1000 |
+
"claims_boundary": {
|
| 1001 |
+
"training_triggered": False,
|
| 1002 |
+
"network_used": False,
|
| 1003 |
+
"proof_credit": 0,
|
| 1004 |
+
"model_trust_delta": 0,
|
| 1005 |
+
"model_promotion_allowed": False,
|
| 1006 |
+
"provenance_inferred": False,
|
| 1007 |
+
},
|
| 1008 |
+
"decisions": decisions,
|
| 1009 |
+
}
|
| 1010 |
+
return _receipted(body, "report_receipt_sha256")
|
| 1011 |
+
|
| 1012 |
+
|
| 1013 |
+
def load_candidate_rows(path: pathlib.Path | str) -> list[Any]:
|
| 1014 |
+
"""Read bounded JSONL or JSON (array or ``{"rows": [...]}``) candidates."""
|
| 1015 |
+
|
| 1016 |
+
source = pathlib.Path(path)
|
| 1017 |
+
if not source.is_file():
|
| 1018 |
+
raise AdmissionInputError("INPUT_FILE_MISSING")
|
| 1019 |
+
if source.stat().st_size > MAX_INPUT_BYTES:
|
| 1020 |
+
raise AdmissionInputError("INPUT_FILE_TOO_LARGE")
|
| 1021 |
+
if source.suffix.lower() == ".jsonl":
|
| 1022 |
+
rows: list[Any] = []
|
| 1023 |
+
try:
|
| 1024 |
+
with source.open("r", encoding="utf-8") as stream:
|
| 1025 |
+
for line_number, line in enumerate(stream, start=1):
|
| 1026 |
+
if not line.strip():
|
| 1027 |
+
continue
|
| 1028 |
+
if len(line.encode("utf-8")) > MAX_ROW_BYTES:
|
| 1029 |
+
raise AdmissionInputError(f"INPUT_JSONL_ROW_TOO_LARGE:{line_number}")
|
| 1030 |
+
try:
|
| 1031 |
+
rows.append(json.loads(line))
|
| 1032 |
+
except json.JSONDecodeError as exc:
|
| 1033 |
+
raise AdmissionInputError(
|
| 1034 |
+
f"INPUT_JSONL_INVALID:{line_number}"
|
| 1035 |
+
) from exc
|
| 1036 |
+
if len(rows) > MAX_ROWS:
|
| 1037 |
+
raise AdmissionInputError("INPUT_ROW_LIMIT_EXCEEDED")
|
| 1038 |
+
except (OSError, UnicodeError) as exc:
|
| 1039 |
+
raise AdmissionInputError("INPUT_JSONL_UNREADABLE") from exc
|
| 1040 |
+
return rows
|
| 1041 |
+
try:
|
| 1042 |
+
payload = json.loads(source.read_text(encoding="utf-8"))
|
| 1043 |
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
| 1044 |
+
raise AdmissionInputError("INPUT_JSON_INVALID") from exc
|
| 1045 |
+
rows = payload.get("rows") if isinstance(payload, Mapping) else payload
|
| 1046 |
+
if not isinstance(rows, list):
|
| 1047 |
+
raise AdmissionInputError("INPUT_JSON_ROWS_ARRAY_REQUIRED")
|
| 1048 |
+
if len(rows) > MAX_ROWS:
|
| 1049 |
+
raise AdmissionInputError("INPUT_ROW_LIMIT_EXCEEDED")
|
| 1050 |
+
return rows
|
| 1051 |
+
|
| 1052 |
+
|
| 1053 |
+
def _jsonl_bytes(rows: Iterable[Mapping[str, Any]]) -> bytes:
|
| 1054 |
+
return b"".join(canonical_bytes(row) + b"\n" for row in rows)
|
| 1055 |
+
|
| 1056 |
+
|
| 1057 |
+
def _atomic_write(path: pathlib.Path, content: bytes) -> None:
|
| 1058 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 1059 |
+
temporary = path.with_name(f".{path.name}.{os.getpid()}.tmp")
|
| 1060 |
+
temporary.write_bytes(content)
|
| 1061 |
+
temporary.replace(path)
|
| 1062 |
+
|
| 1063 |
+
|
| 1064 |
+
def write_artifacts(report: Mapping[str, Any], output_dir: pathlib.Path | str) -> dict[str, Any]:
|
| 1065 |
+
"""Write deterministic admitted/quarantine ledgers plus a receipted report."""
|
| 1066 |
+
|
| 1067 |
+
output = pathlib.Path(output_dir)
|
| 1068 |
+
decisions = list(report.get("decisions") or [])
|
| 1069 |
+
ledgers = {
|
| 1070 |
+
"admitted_train": (
|
| 1071 |
+
"admitted-train.jsonl",
|
| 1072 |
+
[row for row in decisions if row.get("admission_decision") == "ADMIT_TRAIN"],
|
| 1073 |
+
),
|
| 1074 |
+
"admitted_eval": (
|
| 1075 |
+
"admitted-eval.jsonl",
|
| 1076 |
+
[row for row in decisions if row.get("admission_decision") == "ADMIT_EVAL"],
|
| 1077 |
+
),
|
| 1078 |
+
"quarantine": (
|
| 1079 |
+
"quarantine.jsonl",
|
| 1080 |
+
[row for row in decisions if row.get("admission_decision") == "QUARANTINE"],
|
| 1081 |
+
),
|
| 1082 |
+
}
|
| 1083 |
+
artifacts: dict[str, Any] = {}
|
| 1084 |
+
encoded: dict[str, bytes] = {}
|
| 1085 |
+
for key, (name, rows) in ledgers.items():
|
| 1086 |
+
content = _jsonl_bytes(rows)
|
| 1087 |
+
encoded[name] = content
|
| 1088 |
+
artifacts[key] = {
|
| 1089 |
+
"path": name,
|
| 1090 |
+
"rows": len(rows),
|
| 1091 |
+
"bytes": len(content),
|
| 1092 |
+
"sha256": sha256_bytes(content),
|
| 1093 |
+
}
|
| 1094 |
+
body = dict(report)
|
| 1095 |
+
body.pop("report_receipt_sha256", None)
|
| 1096 |
+
body["artifacts"] = artifacts
|
| 1097 |
+
final_report = _receipted(body, "report_receipt_sha256")
|
| 1098 |
+
encoded["admission-report.json"] = (
|
| 1099 |
+
json.dumps(final_report, ensure_ascii=False, sort_keys=True, indent=2) + "\n"
|
| 1100 |
+
).encode("utf-8")
|
| 1101 |
+
for name, content in encoded.items():
|
| 1102 |
+
_atomic_write(output / name, content)
|
| 1103 |
+
return final_report
|
| 1104 |
+
|
| 1105 |
+
|
| 1106 |
+
def admit_file(
|
| 1107 |
+
input_path: pathlib.Path | str,
|
| 1108 |
+
output_dir: pathlib.Path | str,
|
| 1109 |
+
policy: AdmissionPolicy,
|
| 1110 |
+
) -> dict[str, Any]:
|
| 1111 |
+
return write_artifacts(admit_rows(load_candidate_rows(input_path), policy), output_dir)
|
| 1112 |
+
|
| 1113 |
+
|
| 1114 |
+
def _load_protected_hashes(path: str | None) -> frozenset[str]:
|
| 1115 |
+
if path is None:
|
| 1116 |
+
return frozenset()
|
| 1117 |
+
try:
|
| 1118 |
+
value = json.loads(pathlib.Path(path).read_text(encoding="utf-8"))
|
| 1119 |
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
| 1120 |
+
raise AdmissionInputError("PROTECTED_EVAL_HASH_FILE_INVALID") from exc
|
| 1121 |
+
if isinstance(value, Mapping):
|
| 1122 |
+
value = value.get("content_sha256")
|
| 1123 |
+
if not isinstance(value, list) or any(not _is_sha256(item) for item in value):
|
| 1124 |
+
raise AdmissionInputError("PROTECTED_EVAL_HASH_LIST_INVALID")
|
| 1125 |
+
return frozenset(value)
|
| 1126 |
+
|
| 1127 |
+
|
| 1128 |
+
def _load_trusted_signers(path: str | None) -> tuple[TrustedEvidenceSigner, ...]:
|
| 1129 |
+
if path is None:
|
| 1130 |
+
return ()
|
| 1131 |
+
try:
|
| 1132 |
+
value = json.loads(pathlib.Path(path).read_text(encoding="utf-8"))
|
| 1133 |
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
| 1134 |
+
raise AdmissionInputError("TRUST_STORE_FILE_INVALID") from exc
|
| 1135 |
+
if (
|
| 1136 |
+
not isinstance(value, Mapping)
|
| 1137 |
+
or set(value) != {"schema_version", "signers"}
|
| 1138 |
+
or value.get("schema_version") != TRUST_STORE_SCHEMA
|
| 1139 |
+
or not isinstance(value.get("signers"), list)
|
| 1140 |
+
):
|
| 1141 |
+
raise AdmissionInputError("TRUST_STORE_SCHEMA_INVALID")
|
| 1142 |
+
signers: list[TrustedEvidenceSigner] = []
|
| 1143 |
+
required = {
|
| 1144 |
+
"key_id",
|
| 1145 |
+
"issuer",
|
| 1146 |
+
"tool_identity",
|
| 1147 |
+
"public_key_path",
|
| 1148 |
+
"public_key_sha256",
|
| 1149 |
+
}
|
| 1150 |
+
for item in value["signers"]:
|
| 1151 |
+
if not isinstance(item, Mapping) or set(item) != required:
|
| 1152 |
+
raise AdmissionInputError("TRUST_STORE_SIGNER_INVALID")
|
| 1153 |
+
try:
|
| 1154 |
+
signers.append(TrustedEvidenceSigner(**dict(item)))
|
| 1155 |
+
except TypeError as exc:
|
| 1156 |
+
raise AdmissionInputError("TRUST_STORE_SIGNER_INVALID") from exc
|
| 1157 |
+
return tuple(signers)
|
| 1158 |
+
|
| 1159 |
+
|
| 1160 |
+
def _load_evidence_descriptor(path: str | None, error_code: str) -> Mapping[str, str] | None:
|
| 1161 |
+
if path is None:
|
| 1162 |
+
return None
|
| 1163 |
+
try:
|
| 1164 |
+
value = json.loads(pathlib.Path(path).read_text(encoding="utf-8"))
|
| 1165 |
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
| 1166 |
+
raise AdmissionInputError(error_code) from exc
|
| 1167 |
+
if (
|
| 1168 |
+
not isinstance(value, Mapping)
|
| 1169 |
+
or set(value) != {"path", "sha256"}
|
| 1170 |
+
or not isinstance(value.get("path"), str)
|
| 1171 |
+
or not _is_sha256(value.get("sha256"))
|
| 1172 |
+
):
|
| 1173 |
+
raise AdmissionInputError(error_code)
|
| 1174 |
+
return dict(value)
|
| 1175 |
+
|
| 1176 |
+
|
| 1177 |
+
def main(argv: Sequence[str] | None = None) -> int:
|
| 1178 |
+
parser = argparse.ArgumentParser(description=__doc__)
|
| 1179 |
+
parser.add_argument("--input", required=True)
|
| 1180 |
+
parser.add_argument("--output-dir", required=True)
|
| 1181 |
+
parser.add_argument("--evidence-root", required=True)
|
| 1182 |
+
parser.add_argument("--as-of-utc", required=True)
|
| 1183 |
+
parser.add_argument("--max-age-days", type=int, default=365)
|
| 1184 |
+
parser.add_argument("--protected-eval-hashes")
|
| 1185 |
+
parser.add_argument("--trust-store")
|
| 1186 |
+
parser.add_argument("--split-ledger-evidence")
|
| 1187 |
+
args = parser.parse_args(argv)
|
| 1188 |
+
try:
|
| 1189 |
+
policy = AdmissionPolicy(
|
| 1190 |
+
as_of_utc=args.as_of_utc,
|
| 1191 |
+
evidence_root=args.evidence_root,
|
| 1192 |
+
max_age_days=args.max_age_days,
|
| 1193 |
+
protected_eval_content_sha256=_load_protected_hashes(
|
| 1194 |
+
args.protected_eval_hashes
|
| 1195 |
+
),
|
| 1196 |
+
trusted_evidence_signers=_load_trusted_signers(args.trust_store),
|
| 1197 |
+
split_ledger_evidence=_load_evidence_descriptor(
|
| 1198 |
+
args.split_ledger_evidence,
|
| 1199 |
+
"SPLIT_LEDGER_EVIDENCE_DESCRIPTOR_FILE_INVALID",
|
| 1200 |
+
),
|
| 1201 |
+
)
|
| 1202 |
+
report = admit_file(args.input, args.output_dir, policy)
|
| 1203 |
+
except AdmissionInputError as exc:
|
| 1204 |
+
print(json.dumps({"ok": False, "reason_code": str(exc)}, sort_keys=True))
|
| 1205 |
+
return 2
|
| 1206 |
+
print(
|
| 1207 |
+
json.dumps(
|
| 1208 |
+
{
|
| 1209 |
+
"ok": True,
|
| 1210 |
+
"state": report["state"],
|
| 1211 |
+
"summary": report["summary"],
|
| 1212 |
+
"report_receipt_sha256": report["report_receipt_sha256"],
|
| 1213 |
+
},
|
| 1214 |
+
sort_keys=True,
|
| 1215 |
+
)
|
| 1216 |
+
)
|
| 1217 |
+
return 0
|
| 1218 |
+
|
| 1219 |
+
|
| 1220 |
+
if __name__ == "__main__":
|
| 1221 |
+
raise SystemExit(main())
|
|
@@ -0,0 +1,644 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Bounded, content-addressed local corpus admission for the A11oy Brain.
|
| 3 |
+
|
| 4 |
+
This module is intentionally an *admission/status* boundary, not a harvester and not a
|
| 5 |
+
trainer. It reads only three operator-selected JSON manifests, verifies local bytes, and
|
| 6 |
+
classifies every item without changing any Brain trust threshold. Missing sources remain
|
| 7 |
+
``SOURCE_UNAVAILABLE``; malformed, conflicting, or weakly evidenced claims are quarantined.
|
| 8 |
+
|
| 9 |
+
No request parameter can choose a filesystem path. Defaults are repo-confined. An operator
|
| 10 |
+
may opt into one explicit manifest path per source through a named environment variable; an
|
| 11 |
+
explicit manifest may reference only relative artifacts below its own directory.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
from __future__ import annotations
|
| 15 |
+
|
| 16 |
+
import datetime as _datetime
|
| 17 |
+
import hashlib
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
import pathlib
|
| 21 |
+
import re
|
| 22 |
+
from collections import defaultdict
|
| 23 |
+
from typing import Any, Mapping, Sequence
|
| 24 |
+
|
| 25 |
+
SCHEMA_VERSION = "szl.brain.corpus-evidence.v1"
|
| 26 |
+
PROOF_RECEIPT_SCHEMA = "szl.lean-kernel-proof-receipt.v1"
|
| 27 |
+
ARTIFACT_RECEIPT_SCHEMA = "szl.brain.artifact-receipt.v1"
|
| 28 |
+
SOURCE_TYPES = ("szl_lake", "lean_mathlib", "formula")
|
| 29 |
+
EVIDENCE_CLASSES = ("PROVED", "OPEN", "REFUTED", "EXPERIMENTAL", "UNKNOWN")
|
| 30 |
+
|
| 31 |
+
MAX_MANIFEST_BYTES = 8 * 1024 * 1024
|
| 32 |
+
MAX_ARTIFACT_BYTES = 64 * 1024 * 1024
|
| 33 |
+
MAX_ENTRIES = 5_000
|
| 34 |
+
|
| 35 |
+
_SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
|
| 36 |
+
_COMMIT_RE = re.compile(r"^[0-9a-f]{40}$")
|
| 37 |
+
_FORMULA_ID_RE = re.compile(r"^F[1-9][0-9]*$", re.IGNORECASE)
|
| 38 |
+
|
| 39 |
+
DEFAULT_MANIFESTS = {
|
| 40 |
+
"szl_lake": pathlib.Path("data/szl-lake/evidence-manifest.json"),
|
| 41 |
+
"lean_mathlib": pathlib.Path("docs/thesis/v18/lean-corpus-evidence.json"),
|
| 42 |
+
"formula": pathlib.Path("corpus/formulas/formula-corpus-evidence.json"),
|
| 43 |
+
}
|
| 44 |
+
MANIFEST_ENV = {
|
| 45 |
+
"szl_lake": "A11OY_BRAIN_CORPUS_SZL_LAKE_MANIFEST",
|
| 46 |
+
"lean_mathlib": "A11OY_BRAIN_CORPUS_LEAN_MANIFEST",
|
| 47 |
+
"formula": "A11OY_BRAIN_CORPUS_FORMULA_MANIFEST",
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
MANIFEST_CONTRACT = {
|
| 51 |
+
"schema_version": SCHEMA_VERSION,
|
| 52 |
+
"source_types": list(SOURCE_TYPES),
|
| 53 |
+
"evidence_classes": list(EVIDENCE_CLASSES),
|
| 54 |
+
"required_top_level": ["schema_version", "source_type", "version", "entries"],
|
| 55 |
+
"entry_required": ["id", "evidence_class", "source_path", "artifact_sha256"],
|
| 56 |
+
"artifact_receipt_optional": {
|
| 57 |
+
"schema_version": ARTIFACT_RECEIPT_SCHEMA,
|
| 58 |
+
"purpose": (
|
| 59 |
+
"bind the admitted artifact to exact local source bytes and licenses; this "
|
| 60 |
+
"receipt never grants mathematical proof credit"
|
| 61 |
+
),
|
| 62 |
+
},
|
| 63 |
+
"proof_receipt_required_for_proved": [
|
| 64 |
+
"schema_version", "verified", "artifact_sha256", "sorry_count",
|
| 65 |
+
"kernel_commit", "lean_commit", "mathlib_commit", "receipt_sha256",
|
| 66 |
+
],
|
| 67 |
+
"proof_rule": (
|
| 68 |
+
"PROVED requires verified local artifact bytes, zero sorry/admit obligations, an exact "
|
| 69 |
+
"40-hex kernel/Lean/mathlib commit triple matching the manifest toolchain, and a valid "
|
| 70 |
+
"content-addressed kernel receipt"
|
| 71 |
+
),
|
| 72 |
+
"non_uplift_rule": (
|
| 73 |
+
"OPEN, REFUTED, EXPERIMENTAL, UNKNOWN, invalid PROVED claims, and F-ID conflicts "
|
| 74 |
+
"receive zero proof credit and cannot raise query trust"
|
| 75 |
+
),
|
| 76 |
+
"path_rule": (
|
| 77 |
+
"default manifests and artifacts are repo-confined; explicitly configured manifests "
|
| 78 |
+
"may read only relative artifacts confined below that manifest's directory"
|
| 79 |
+
),
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def _utc_now() -> str:
|
| 84 |
+
return _datetime.datetime.now(_datetime.timezone.utc).isoformat()
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def _canonical_json_bytes(value: Any) -> bytes:
|
| 88 |
+
return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def sha256_json(value: Any) -> str:
|
| 92 |
+
"""Return the canonical JSON SHA-256 used by proof receipts and fixture builders."""
|
| 93 |
+
return hashlib.sha256(_canonical_json_bytes(value)).hexdigest()
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def _sha256_file(path: pathlib.Path, maximum: int) -> tuple[str | None, int, str | None]:
|
| 97 |
+
try:
|
| 98 |
+
size = path.stat().st_size
|
| 99 |
+
if size > maximum:
|
| 100 |
+
return None, size, f"FILE_TOO_LARGE:{size}>{maximum}"
|
| 101 |
+
digest = hashlib.sha256()
|
| 102 |
+
read = 0
|
| 103 |
+
with path.open("rb") as stream:
|
| 104 |
+
while True:
|
| 105 |
+
chunk = stream.read(1024 * 1024)
|
| 106 |
+
if not chunk:
|
| 107 |
+
break
|
| 108 |
+
read += len(chunk)
|
| 109 |
+
if read > maximum:
|
| 110 |
+
return None, read, f"FILE_TOO_LARGE:{read}>{maximum}"
|
| 111 |
+
digest.update(chunk)
|
| 112 |
+
return digest.hexdigest(), read, None
|
| 113 |
+
except OSError as exc:
|
| 114 |
+
return None, 0, f"READ_FAILED:{type(exc).__name__}"
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def _read_file_bounded(path: pathlib.Path, maximum: int) -> tuple[bytes | None, str | None]:
|
| 118 |
+
"""Read once so the bytes parsed are exactly the bytes that receive the content hash."""
|
| 119 |
+
try:
|
| 120 |
+
with path.open("rb") as stream:
|
| 121 |
+
raw = stream.read(maximum + 1)
|
| 122 |
+
if len(raw) > maximum:
|
| 123 |
+
return None, f"FILE_TOO_LARGE:{len(raw)}>{maximum}"
|
| 124 |
+
return raw, None
|
| 125 |
+
except OSError as exc:
|
| 126 |
+
return None, f"READ_FAILED:{type(exc).__name__}"
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def _inside(path: pathlib.Path, boundary: pathlib.Path) -> bool:
|
| 130 |
+
try:
|
| 131 |
+
path.relative_to(boundary)
|
| 132 |
+
return True
|
| 133 |
+
except ValueError:
|
| 134 |
+
return False
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def _safe_manifest_path(
|
| 138 |
+
source_type: str,
|
| 139 |
+
repo_root: pathlib.Path,
|
| 140 |
+
environ: Mapping[str, str],
|
| 141 |
+
) -> tuple[pathlib.Path, pathlib.Path, str, str | None]:
|
| 142 |
+
"""Resolve one fixed source path; no API/user value participates in this decision."""
|
| 143 |
+
env_name = MANIFEST_ENV[source_type]
|
| 144 |
+
configured = str(environ.get(env_name, "")).strip()
|
| 145 |
+
root = repo_root.resolve()
|
| 146 |
+
if configured:
|
| 147 |
+
raw = pathlib.Path(configured).expanduser()
|
| 148 |
+
path = (root / raw if not raw.is_absolute() else raw).resolve()
|
| 149 |
+
boundary = path.parent
|
| 150 |
+
origin = f"EXPLICIT_CONFIG:{env_name}"
|
| 151 |
+
else:
|
| 152 |
+
path = (root / DEFAULT_MANIFESTS[source_type]).resolve()
|
| 153 |
+
boundary = root
|
| 154 |
+
origin = "REPO_DEFAULT"
|
| 155 |
+
if not _inside(path, root):
|
| 156 |
+
return path, boundary, origin, "MANIFEST_PATH_ESCAPES_REPO"
|
| 157 |
+
if path.suffix.lower() != ".json":
|
| 158 |
+
return path, boundary, origin, "MANIFEST_MUST_BE_JSON"
|
| 159 |
+
return path, boundary, origin, None
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
def _entry_shell(entry: Any, source_type: str, ordinal: int) -> dict[str, Any]:
|
| 163 |
+
entry_id = entry.get("id") if isinstance(entry, dict) else None
|
| 164 |
+
return {
|
| 165 |
+
"id": str(entry_id or f"entry-{ordinal}"),
|
| 166 |
+
"source_type": source_type,
|
| 167 |
+
"declared_class": "UNKNOWN",
|
| 168 |
+
"effective_class": "UNKNOWN",
|
| 169 |
+
"artifact_sha256": None,
|
| 170 |
+
"artifact_verified": False,
|
| 171 |
+
"artifact_receipt_valid": False,
|
| 172 |
+
"proof_receipt_valid": False,
|
| 173 |
+
"proof_credit": 0,
|
| 174 |
+
"trust_uplift_eligible": False,
|
| 175 |
+
"disposition": "QUARANTINED",
|
| 176 |
+
"quarantine_reasons": [],
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def _validate_artifact_receipt(
|
| 181 |
+
receipt: Any,
|
| 182 |
+
artifact_sha256: str,
|
| 183 |
+
artifact_boundary: pathlib.Path,
|
| 184 |
+
) -> tuple[bool, list[str], dict[str, Any] | None]:
|
| 185 |
+
"""Verify an optional local-byte receipt without upgrading proof status."""
|
| 186 |
+
if receipt is None:
|
| 187 |
+
return False, [], None
|
| 188 |
+
if not isinstance(receipt, dict):
|
| 189 |
+
return False, ["ARTIFACT_RECEIPT_NOT_OBJECT"], None
|
| 190 |
+
reasons: list[str] = []
|
| 191 |
+
if receipt.get("schema_version") != ARTIFACT_RECEIPT_SCHEMA:
|
| 192 |
+
reasons.append("ARTIFACT_RECEIPT_SCHEMA_MISMATCH")
|
| 193 |
+
if receipt.get("verified") is not True:
|
| 194 |
+
reasons.append("ARTIFACT_RECEIPT_NOT_VERIFIED")
|
| 195 |
+
if str(receipt.get("artifact_sha256") or "").lower() != artifact_sha256:
|
| 196 |
+
reasons.append("ARTIFACT_RECEIPT_ARTIFACT_MISMATCH")
|
| 197 |
+
if receipt.get("proof_credit") not in {0, 0.0}:
|
| 198 |
+
reasons.append("ARTIFACT_RECEIPT_PROOF_CREDIT_FORBIDDEN")
|
| 199 |
+
|
| 200 |
+
assets = receipt.get("source_assets")
|
| 201 |
+
if not isinstance(assets, list) or not assets:
|
| 202 |
+
reasons.append("ARTIFACT_RECEIPT_SOURCE_ASSETS_REQUIRED")
|
| 203 |
+
assets = []
|
| 204 |
+
elif len(assets) > 128:
|
| 205 |
+
reasons.append("ARTIFACT_RECEIPT_TOO_MANY_SOURCE_ASSETS")
|
| 206 |
+
assets = assets[:128]
|
| 207 |
+
public_assets: list[dict[str, Any]] = []
|
| 208 |
+
for ordinal, asset in enumerate(assets):
|
| 209 |
+
if not isinstance(asset, dict):
|
| 210 |
+
reasons.append(f"ARTIFACT_RECEIPT_ASSET_NOT_OBJECT:{ordinal}")
|
| 211 |
+
continue
|
| 212 |
+
path_value = str(asset.get("path") or "").strip()
|
| 213 |
+
expected = str(asset.get("sha256") or "").lower()
|
| 214 |
+
license_id = str(asset.get("license") or "").strip()
|
| 215 |
+
if not path_value:
|
| 216 |
+
reasons.append(f"ARTIFACT_RECEIPT_ASSET_PATH_REQUIRED:{ordinal}")
|
| 217 |
+
continue
|
| 218 |
+
relative = pathlib.Path(path_value)
|
| 219 |
+
path = (artifact_boundary / relative).resolve() if not relative.is_absolute() else None
|
| 220 |
+
if path is None or not _inside(path, artifact_boundary):
|
| 221 |
+
reasons.append(f"ARTIFACT_RECEIPT_ASSET_PATH_FORBIDDEN:{ordinal}")
|
| 222 |
+
continue
|
| 223 |
+
if not _SHA256_RE.fullmatch(expected):
|
| 224 |
+
reasons.append(f"ARTIFACT_RECEIPT_ASSET_SHA_INVALID:{ordinal}")
|
| 225 |
+
if not license_id or license_id.upper() == "UNKNOWN":
|
| 226 |
+
reasons.append(f"ARTIFACT_RECEIPT_ASSET_LICENSE_UNKNOWN:{ordinal}")
|
| 227 |
+
actual, size, read_error = _sha256_file(path, MAX_ARTIFACT_BYTES)
|
| 228 |
+
if read_error:
|
| 229 |
+
reasons.append(f"ARTIFACT_RECEIPT_ASSET_{read_error}:{ordinal}")
|
| 230 |
+
elif actual != expected:
|
| 231 |
+
reasons.append(f"ARTIFACT_RECEIPT_ASSET_SHA_MISMATCH:{ordinal}")
|
| 232 |
+
public_assets.append({
|
| 233 |
+
"path": path_value.replace("\\", "/"),
|
| 234 |
+
"sha256": expected or None,
|
| 235 |
+
"license": license_id or None,
|
| 236 |
+
"bytes": size,
|
| 237 |
+
})
|
| 238 |
+
|
| 239 |
+
stored = str(receipt.get("receipt_sha256") or "").lower()
|
| 240 |
+
body = {key: value for key, value in receipt.items() if key != "receipt_sha256"}
|
| 241 |
+
if not _SHA256_RE.fullmatch(stored) or stored != sha256_json(body):
|
| 242 |
+
reasons.append("ARTIFACT_RECEIPT_DIGEST_MISMATCH")
|
| 243 |
+
public = {
|
| 244 |
+
"schema_version": receipt.get("schema_version"),
|
| 245 |
+
"verified": receipt.get("verified") is True,
|
| 246 |
+
"artifact_sha256": str(receipt.get("artifact_sha256") or "").lower() or None,
|
| 247 |
+
"proof_credit": receipt.get("proof_credit"),
|
| 248 |
+
"source_asset_count": len(public_assets),
|
| 249 |
+
"source_assets": public_assets,
|
| 250 |
+
"receipt_sha256": stored or None,
|
| 251 |
+
}
|
| 252 |
+
return not reasons, reasons, public
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
def _validate_toolchain(manifest: Mapping[str, Any]) -> tuple[dict[str, str], list[str]]:
|
| 256 |
+
raw = manifest.get("toolchain")
|
| 257 |
+
if not isinstance(raw, dict):
|
| 258 |
+
return {}, ["TOOLCHAIN_REQUIRED_FOR_PROVED"]
|
| 259 |
+
toolchain: dict[str, str] = {}
|
| 260 |
+
reasons: list[str] = []
|
| 261 |
+
for name in ("kernel_commit", "lean_commit", "mathlib_commit"):
|
| 262 |
+
value = str(raw.get(name) or "").lower()
|
| 263 |
+
if not _COMMIT_RE.fullmatch(value):
|
| 264 |
+
reasons.append(f"INVALID_EXACT_{name.upper()}")
|
| 265 |
+
else:
|
| 266 |
+
toolchain[name] = value
|
| 267 |
+
return toolchain, reasons
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
def _validate_receipt(
|
| 271 |
+
receipt: Any,
|
| 272 |
+
artifact_sha256: str,
|
| 273 |
+
toolchain: Mapping[str, str],
|
| 274 |
+
) -> tuple[bool, list[str], dict[str, Any] | None]:
|
| 275 |
+
if not isinstance(receipt, dict):
|
| 276 |
+
return False, ["KERNEL_RECEIPT_REQUIRED"], None
|
| 277 |
+
reasons: list[str] = []
|
| 278 |
+
if receipt.get("schema_version") != PROOF_RECEIPT_SCHEMA:
|
| 279 |
+
reasons.append("KERNEL_RECEIPT_SCHEMA_MISMATCH")
|
| 280 |
+
if receipt.get("verified") is not True:
|
| 281 |
+
reasons.append("KERNEL_RECEIPT_NOT_VERIFIED")
|
| 282 |
+
if receipt.get("artifact_sha256") != artifact_sha256:
|
| 283 |
+
reasons.append("KERNEL_RECEIPT_ARTIFACT_MISMATCH")
|
| 284 |
+
try:
|
| 285 |
+
receipt_sorries = int(receipt.get("sorry_count"))
|
| 286 |
+
except (TypeError, ValueError):
|
| 287 |
+
receipt_sorries = -1
|
| 288 |
+
if receipt_sorries != 0:
|
| 289 |
+
reasons.append("KERNEL_RECEIPT_NOT_ZERO_SORRY")
|
| 290 |
+
for name in ("kernel_commit", "lean_commit", "mathlib_commit"):
|
| 291 |
+
value = str(receipt.get(name) or "").lower()
|
| 292 |
+
if not _COMMIT_RE.fullmatch(value):
|
| 293 |
+
reasons.append(f"KERNEL_RECEIPT_INVALID_{name.upper()}")
|
| 294 |
+
elif value != toolchain.get(name):
|
| 295 |
+
reasons.append(f"KERNEL_RECEIPT_{name.upper()}_MISMATCH")
|
| 296 |
+
stored = str(receipt.get("receipt_sha256") or "").lower()
|
| 297 |
+
body = {key: value for key, value in receipt.items() if key != "receipt_sha256"}
|
| 298 |
+
computed = sha256_json(body)
|
| 299 |
+
if not _SHA256_RE.fullmatch(stored) or stored != computed:
|
| 300 |
+
reasons.append("KERNEL_RECEIPT_DIGEST_MISMATCH")
|
| 301 |
+
public = {
|
| 302 |
+
"schema_version": receipt.get("schema_version"),
|
| 303 |
+
"verified": receipt.get("verified") is True,
|
| 304 |
+
"sorry_count": receipt_sorries,
|
| 305 |
+
"kernel_commit": receipt.get("kernel_commit"),
|
| 306 |
+
"lean_commit": receipt.get("lean_commit"),
|
| 307 |
+
"mathlib_commit": receipt.get("mathlib_commit"),
|
| 308 |
+
"receipt_sha256": stored or None,
|
| 309 |
+
}
|
| 310 |
+
return not reasons, reasons, public
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
def _validate_entry(
|
| 314 |
+
entry: Any,
|
| 315 |
+
source_type: str,
|
| 316 |
+
ordinal: int,
|
| 317 |
+
artifact_boundary: pathlib.Path,
|
| 318 |
+
toolchain: Mapping[str, str],
|
| 319 |
+
) -> dict[str, Any]:
|
| 320 |
+
out = _entry_shell(entry, source_type, ordinal)
|
| 321 |
+
reasons: list[str] = out["quarantine_reasons"]
|
| 322 |
+
if not isinstance(entry, dict):
|
| 323 |
+
reasons.append("ENTRY_NOT_OBJECT")
|
| 324 |
+
return out
|
| 325 |
+
|
| 326 |
+
entry_id = str(entry.get("id") or "").strip()
|
| 327 |
+
if not entry_id:
|
| 328 |
+
reasons.append("ENTRY_ID_REQUIRED")
|
| 329 |
+
else:
|
| 330 |
+
out["id"] = entry_id.upper() if _FORMULA_ID_RE.fullmatch(entry_id) else entry_id
|
| 331 |
+
|
| 332 |
+
declared = str(entry.get("evidence_class") or "UNKNOWN").upper()
|
| 333 |
+
if declared not in EVIDENCE_CLASSES:
|
| 334 |
+
reasons.append("INVALID_EVIDENCE_CLASS")
|
| 335 |
+
declared = "UNKNOWN"
|
| 336 |
+
out["declared_class"] = declared
|
| 337 |
+
out["effective_class"] = declared
|
| 338 |
+
|
| 339 |
+
expected = str(entry.get("artifact_sha256") or "").lower()
|
| 340 |
+
out["artifact_sha256"] = expected or None
|
| 341 |
+
if not _SHA256_RE.fullmatch(expected):
|
| 342 |
+
reasons.append("INVALID_ARTIFACT_SHA256")
|
| 343 |
+
|
| 344 |
+
source_path = entry.get("source_path")
|
| 345 |
+
if not isinstance(source_path, str) or not source_path.strip():
|
| 346 |
+
reasons.append("SOURCE_PATH_REQUIRED")
|
| 347 |
+
artifact_path = None
|
| 348 |
+
else:
|
| 349 |
+
relative = pathlib.Path(source_path.strip())
|
| 350 |
+
if relative.is_absolute():
|
| 351 |
+
reasons.append("ABSOLUTE_ARTIFACT_PATH_FORBIDDEN")
|
| 352 |
+
artifact_path = None
|
| 353 |
+
else:
|
| 354 |
+
artifact_path = (artifact_boundary / relative).resolve()
|
| 355 |
+
if not _inside(artifact_path, artifact_boundary):
|
| 356 |
+
reasons.append("ARTIFACT_PATH_ESCAPES_BOUNDARY")
|
| 357 |
+
artifact_path = None
|
| 358 |
+
|
| 359 |
+
if artifact_path is not None:
|
| 360 |
+
out["source_path"] = source_path.replace("\\", "/")
|
| 361 |
+
if not artifact_path.is_file():
|
| 362 |
+
reasons.append("ARTIFACT_SOURCE_UNAVAILABLE")
|
| 363 |
+
else:
|
| 364 |
+
actual, size, read_error = _sha256_file(artifact_path, MAX_ARTIFACT_BYTES)
|
| 365 |
+
out["artifact_bytes"] = size
|
| 366 |
+
out["computed_artifact_sha256"] = actual
|
| 367 |
+
if read_error:
|
| 368 |
+
reasons.append(read_error)
|
| 369 |
+
elif actual != expected:
|
| 370 |
+
reasons.append("ARTIFACT_SHA256_MISMATCH")
|
| 371 |
+
else:
|
| 372 |
+
out["artifact_verified"] = True
|
| 373 |
+
|
| 374 |
+
try:
|
| 375 |
+
sorry_count = int(entry.get("sorry_count", 0))
|
| 376 |
+
except (TypeError, ValueError):
|
| 377 |
+
sorry_count = -1
|
| 378 |
+
if sorry_count < 0:
|
| 379 |
+
reasons.append("INVALID_SORRY_COUNT")
|
| 380 |
+
sorry_count = 0
|
| 381 |
+
out["sorry_count"] = sorry_count
|
| 382 |
+
|
| 383 |
+
artifact_receipt_valid, artifact_receipt_reasons, artifact_receipt_public = (
|
| 384 |
+
_validate_artifact_receipt(entry.get("artifact_receipt"), expected, artifact_boundary)
|
| 385 |
+
)
|
| 386 |
+
reasons.extend(artifact_receipt_reasons)
|
| 387 |
+
out["artifact_receipt_valid"] = artifact_receipt_valid
|
| 388 |
+
out["artifact_receipt"] = artifact_receipt_public
|
| 389 |
+
|
| 390 |
+
if declared == "PROVED":
|
| 391 |
+
if sorry_count != 0:
|
| 392 |
+
reasons.append("PROVED_REQUIRES_ZERO_SORRY")
|
| 393 |
+
valid_receipt, receipt_reasons, receipt_public = _validate_receipt(
|
| 394 |
+
entry.get("proof_receipt"), expected, toolchain,
|
| 395 |
+
)
|
| 396 |
+
reasons.extend(receipt_reasons)
|
| 397 |
+
out["proof_receipt"] = receipt_public
|
| 398 |
+
out["proof_receipt_valid"] = valid_receipt
|
| 399 |
+
if reasons or not out["artifact_verified"] or not valid_receipt:
|
| 400 |
+
out["effective_class"] = "UNKNOWN"
|
| 401 |
+
else:
|
| 402 |
+
out["proof_receipt"] = None
|
| 403 |
+
out["proof_receipt_valid"] = False
|
| 404 |
+
|
| 405 |
+
proof_eligible = bool(
|
| 406 |
+
declared == "PROVED"
|
| 407 |
+
and out["effective_class"] == "PROVED"
|
| 408 |
+
and out["artifact_verified"]
|
| 409 |
+
and out["proof_receipt_valid"]
|
| 410 |
+
and not reasons
|
| 411 |
+
)
|
| 412 |
+
out["proof_credit"] = 1 if proof_eligible else 0
|
| 413 |
+
out["trust_uplift_eligible"] = proof_eligible
|
| 414 |
+
if proof_eligible:
|
| 415 |
+
out["disposition"] = "ADMITTED_PROOF_EVIDENCE"
|
| 416 |
+
elif not reasons and declared in {"OPEN", "REFUTED", "EXPERIMENTAL", "UNKNOWN"}:
|
| 417 |
+
out["disposition"] = "QUARANTINED_NON_PROOF"
|
| 418 |
+
reasons.append(f"{declared}_HAS_ZERO_PROOF_CREDIT")
|
| 419 |
+
elif reasons:
|
| 420 |
+
out["effective_class"] = "UNKNOWN"
|
| 421 |
+
return out
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
def _load_manifest(
|
| 425 |
+
source_type: str,
|
| 426 |
+
manifest_path: pathlib.Path,
|
| 427 |
+
artifact_boundary: pathlib.Path,
|
| 428 |
+
origin: str,
|
| 429 |
+
) -> dict[str, Any]:
|
| 430 |
+
public_path = (
|
| 431 |
+
manifest_path.relative_to(artifact_boundary).as_posix()
|
| 432 |
+
if origin == "REPO_DEFAULT"
|
| 433 |
+
else f"<explicit-config>/{manifest_path.name}"
|
| 434 |
+
)
|
| 435 |
+
base: dict[str, Any] = {
|
| 436 |
+
"source_type": source_type,
|
| 437 |
+
"status": "SOURCE_UNAVAILABLE",
|
| 438 |
+
"manifest_origin": origin,
|
| 439 |
+
"manifest_path": public_path,
|
| 440 |
+
"entries": [],
|
| 441 |
+
"counts": {name: 0 for name in EVIDENCE_CLASSES},
|
| 442 |
+
"proof_credit": 0,
|
| 443 |
+
"errors": [],
|
| 444 |
+
}
|
| 445 |
+
if not manifest_path.is_file():
|
| 446 |
+
base["errors"] = ["MANIFEST_NOT_FOUND"]
|
| 447 |
+
return base
|
| 448 |
+
raw, read_error = _read_file_bounded(manifest_path, MAX_MANIFEST_BYTES)
|
| 449 |
+
base["manifest_sha256"] = hashlib.sha256(raw).hexdigest() if raw is not None else None
|
| 450 |
+
base["manifest_bytes"] = len(raw) if raw is not None else 0
|
| 451 |
+
if read_error:
|
| 452 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 453 |
+
base["errors"] = [read_error]
|
| 454 |
+
return base
|
| 455 |
+
try:
|
| 456 |
+
manifest = json.loads(raw.decode("utf-8"))
|
| 457 |
+
except (UnicodeError, json.JSONDecodeError) as exc:
|
| 458 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 459 |
+
base["errors"] = [f"INVALID_JSON:{type(exc).__name__}"]
|
| 460 |
+
return base
|
| 461 |
+
if not isinstance(manifest, dict):
|
| 462 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 463 |
+
base["errors"] = ["MANIFEST_NOT_OBJECT"]
|
| 464 |
+
return base
|
| 465 |
+
if manifest.get("schema_version") != SCHEMA_VERSION:
|
| 466 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 467 |
+
base["errors"] = ["SCHEMA_VERSION_MISMATCH"]
|
| 468 |
+
return base
|
| 469 |
+
if manifest.get("source_type") != source_type:
|
| 470 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 471 |
+
base["errors"] = ["SOURCE_TYPE_MISMATCH"]
|
| 472 |
+
return base
|
| 473 |
+
if not isinstance(manifest.get("version"), str) or not manifest["version"].strip():
|
| 474 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 475 |
+
base["errors"] = ["VERSION_REQUIRED"]
|
| 476 |
+
return base
|
| 477 |
+
entries = manifest.get("entries")
|
| 478 |
+
if not isinstance(entries, list):
|
| 479 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 480 |
+
base["errors"] = ["ENTRIES_MUST_BE_ARRAY"]
|
| 481 |
+
return base
|
| 482 |
+
if len(entries) > MAX_ENTRIES:
|
| 483 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 484 |
+
base["errors"] = [f"TOO_MANY_ENTRIES:{len(entries)}>{MAX_ENTRIES}"]
|
| 485 |
+
return base
|
| 486 |
+
|
| 487 |
+
expected_manifest_digest = manifest.get("content_sha256")
|
| 488 |
+
if expected_manifest_digest is not None:
|
| 489 |
+
body = {key: value for key, value in manifest.items() if key != "content_sha256"}
|
| 490 |
+
actual_manifest_digest = sha256_json(body)
|
| 491 |
+
base["manifest_content_sha256"] = actual_manifest_digest
|
| 492 |
+
if (not isinstance(expected_manifest_digest, str)
|
| 493 |
+
or expected_manifest_digest.lower() != actual_manifest_digest):
|
| 494 |
+
base["status"] = "MANIFEST_QUARANTINED"
|
| 495 |
+
base["errors"] = ["MANIFEST_CONTENT_DIGEST_MISMATCH"]
|
| 496 |
+
return base
|
| 497 |
+
|
| 498 |
+
toolchain, toolchain_errors = _validate_toolchain(manifest)
|
| 499 |
+
if any(str(e.get("evidence_class") or "").upper() == "PROVED"
|
| 500 |
+
for e in entries if isinstance(e, dict)) and toolchain_errors:
|
| 501 |
+
base["errors"].extend(toolchain_errors)
|
| 502 |
+
base["version"] = manifest["version"]
|
| 503 |
+
base["toolchain"] = toolchain or None
|
| 504 |
+
base["entries"] = [
|
| 505 |
+
_validate_entry(e, source_type, i, artifact_boundary, toolchain)
|
| 506 |
+
for i, e in enumerate(entries)
|
| 507 |
+
]
|
| 508 |
+
for entry in base["entries"]:
|
| 509 |
+
base["counts"][entry["effective_class"]] += 1
|
| 510 |
+
base["proof_credit"] += entry["proof_credit"]
|
| 511 |
+
quarantined = sum(e["disposition"].startswith("QUARANTINED") for e in base["entries"])
|
| 512 |
+
if base["errors"] or quarantined:
|
| 513 |
+
base["status"] = "PARTIAL_QUARANTINE" if base["entries"] else "MANIFEST_QUARANTINED"
|
| 514 |
+
else:
|
| 515 |
+
base["status"] = "INGESTED_LOCAL"
|
| 516 |
+
return base
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
def _apply_formula_id_conflicts(sources: Sequence[dict[str, Any]]) -> list[dict[str, Any]]:
|
| 520 |
+
by_id: dict[str, list[dict[str, Any]]] = defaultdict(list)
|
| 521 |
+
for source in sources:
|
| 522 |
+
for entry in source.get("entries", []):
|
| 523 |
+
entry_id = str(entry.get("id") or "").upper()
|
| 524 |
+
if _FORMULA_ID_RE.fullmatch(entry_id):
|
| 525 |
+
by_id[entry_id].append(entry)
|
| 526 |
+
conflicts: list[dict[str, Any]] = []
|
| 527 |
+
for formula_id, rows in sorted(by_id.items()):
|
| 528 |
+
signatures = {
|
| 529 |
+
(
|
| 530 |
+
row.get("artifact_sha256"), row.get("effective_class"),
|
| 531 |
+
(row.get("proof_receipt") or {}).get("receipt_sha256"),
|
| 532 |
+
)
|
| 533 |
+
for row in rows
|
| 534 |
+
}
|
| 535 |
+
if len(signatures) <= 1:
|
| 536 |
+
continue
|
| 537 |
+
conflicts.append({
|
| 538 |
+
"formula_id": formula_id,
|
| 539 |
+
"reason": "F_ID_CONFLICT",
|
| 540 |
+
"variants": len(signatures),
|
| 541 |
+
"sources": sorted({str(row.get("source_type")) for row in rows}),
|
| 542 |
+
})
|
| 543 |
+
for row in rows:
|
| 544 |
+
row["disposition"] = "QUARANTINED"
|
| 545 |
+
row["effective_class"] = "UNKNOWN"
|
| 546 |
+
row["proof_credit"] = 0
|
| 547 |
+
row["trust_uplift_eligible"] = False
|
| 548 |
+
row.setdefault("quarantine_reasons", []).append("F_ID_CONFLICT")
|
| 549 |
+
return conflicts
|
| 550 |
+
|
| 551 |
+
|
| 552 |
+
def build_corpus_status(
|
| 553 |
+
repo_root: pathlib.Path | str | None = None,
|
| 554 |
+
environ: Mapping[str, str] | None = None,
|
| 555 |
+
) -> dict[str, Any]:
|
| 556 |
+
"""Build a bounded, read-only admission status from local canonical manifests."""
|
| 557 |
+
root = pathlib.Path(repo_root or pathlib.Path(__file__).resolve().parent).resolve()
|
| 558 |
+
env = os.environ if environ is None else environ
|
| 559 |
+
sources: list[dict[str, Any]] = []
|
| 560 |
+
for source_type in SOURCE_TYPES:
|
| 561 |
+
manifest_path, boundary, origin, path_error = _safe_manifest_path(source_type, root, env)
|
| 562 |
+
if path_error:
|
| 563 |
+
sources.append({
|
| 564 |
+
"source_type": source_type,
|
| 565 |
+
"status": "SOURCE_UNAVAILABLE",
|
| 566 |
+
"manifest_origin": origin,
|
| 567 |
+
"manifest_path": (
|
| 568 |
+
manifest_path.relative_to(root).as_posix()
|
| 569 |
+
if origin == "REPO_DEFAULT" and _inside(manifest_path, root)
|
| 570 |
+
else f"<explicit-config>/{manifest_path.name}"
|
| 571 |
+
),
|
| 572 |
+
"entries": [],
|
| 573 |
+
"counts": {name: 0 for name in EVIDENCE_CLASSES},
|
| 574 |
+
"proof_credit": 0,
|
| 575 |
+
"errors": [path_error],
|
| 576 |
+
})
|
| 577 |
+
continue
|
| 578 |
+
# Default artifacts are repo-confined. Explicit external artifacts are confined below
|
| 579 |
+
# the explicit manifest directory; the environment is the sole operator trust boundary.
|
| 580 |
+
artifact_boundary = root if origin == "REPO_DEFAULT" else boundary
|
| 581 |
+
sources.append(_load_manifest(source_type, manifest_path, artifact_boundary, origin))
|
| 582 |
+
|
| 583 |
+
conflicts = _apply_formula_id_conflicts(sources)
|
| 584 |
+
counts = {name: 0 for name in EVIDENCE_CLASSES}
|
| 585 |
+
proof_credit = 0
|
| 586 |
+
quarantined_entries = 0
|
| 587 |
+
for source in sources:
|
| 588 |
+
source["counts"] = {name: 0 for name in EVIDENCE_CLASSES}
|
| 589 |
+
source["proof_credit"] = 0
|
| 590 |
+
for entry in source.get("entries", []):
|
| 591 |
+
source["counts"][entry["effective_class"]] += 1
|
| 592 |
+
source["proof_credit"] += entry["proof_credit"]
|
| 593 |
+
counts[entry["effective_class"]] += 1
|
| 594 |
+
proof_credit += entry["proof_credit"]
|
| 595 |
+
quarantined_entries += int(entry["disposition"].startswith("QUARANTINED"))
|
| 596 |
+
if any("F_ID_CONFLICT" in e.get("quarantine_reasons", []) for e in source.get("entries", [])):
|
| 597 |
+
source["status"] = "PARTIAL_QUARANTINE"
|
| 598 |
+
|
| 599 |
+
corpus_operational = any(
|
| 600 |
+
source["status"] in {"INGESTED_LOCAL", "PARTIAL_QUARANTINE"}
|
| 601 |
+
and bool(source.get("entries"))
|
| 602 |
+
for source in sources
|
| 603 |
+
)
|
| 604 |
+
|
| 605 |
+
return {
|
| 606 |
+
"ok": True,
|
| 607 |
+
"endpoint": "brain/health/corpus-sources",
|
| 608 |
+
"label": "MEASURED",
|
| 609 |
+
"schema_version": SCHEMA_VERSION,
|
| 610 |
+
"manifest_contract": MANIFEST_CONTRACT,
|
| 611 |
+
"sources": sources,
|
| 612 |
+
"formula_id_conflicts": conflicts,
|
| 613 |
+
"summary": {
|
| 614 |
+
"counts": counts,
|
| 615 |
+
"proof_credit": proof_credit,
|
| 616 |
+
"quarantined_entries": quarantined_entries,
|
| 617 |
+
"trust_uplift_from_non_proved": 0,
|
| 618 |
+
"missing_sources": sum(s["status"] == "SOURCE_UNAVAILABLE" for s in sources),
|
| 619 |
+
"corpus_operational": corpus_operational,
|
| 620 |
+
"proof_admission_available": proof_credit > 0,
|
| 621 |
+
"network_access": False,
|
| 622 |
+
"gpu_training_started": False,
|
| 623 |
+
"writes_performed": 0,
|
| 624 |
+
"trust_thresholds_changed": False,
|
| 625 |
+
},
|
| 626 |
+
"note": (
|
| 627 |
+
"This is admission evidence, not a proof-count claim. Legacy/Hugging Face snapshots "
|
| 628 |
+
"are not translated into the canonical contract; missing sources remain unavailable."
|
| 629 |
+
),
|
| 630 |
+
"timestamp_utc": _utc_now(),
|
| 631 |
+
}
|
| 632 |
+
|
| 633 |
+
|
| 634 |
+
def info() -> dict[str, Any]:
|
| 635 |
+
"""Static, side-effect-free contract description for documentation and tests."""
|
| 636 |
+
return {
|
| 637 |
+
"service": "a11oy.brain.corpus-admission",
|
| 638 |
+
"schema_version": SCHEMA_VERSION,
|
| 639 |
+
"contract": MANIFEST_CONTRACT,
|
| 640 |
+
"effectors": 0,
|
| 641 |
+
"network_access": False,
|
| 642 |
+
"gpu_training": False,
|
| 643 |
+
"request_selected_paths": False,
|
| 644 |
+
}
|
|
@@ -54,9 +54,14 @@ import datetime
|
|
| 54 |
import hashlib
|
| 55 |
import importlib
|
| 56 |
import json
|
|
|
|
| 57 |
import re
|
|
|
|
|
|
|
| 58 |
from typing import Any, Callable
|
| 59 |
|
|
|
|
|
|
|
| 60 |
try: # numpy is allowed; used only for the modeled mean, guarded so a missing wheel is honest.
|
| 61 |
import numpy as _np
|
| 62 |
_HAVE_NUMPY = True
|
|
@@ -92,6 +97,25 @@ DEGRADED = "DEGRADED"
|
|
| 92 |
UNTRUSTWORTHY = "UNTRUSTWORTHY"
|
| 93 |
INSUFFICIENT_SIGNAL = "INSUFFICIENT-SIGNAL"
|
| 94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
VERDICTS = (TRUSTWORTHY, DEGRADED, UNTRUSTWORTHY, INSUFFICIENT_SIGNAL)
|
| 96 |
|
| 97 |
# Minimum available components required to render a confident verdict; below this the honest
|
|
@@ -148,7 +172,7 @@ COMPONENTS: list[dict] = [
|
|
| 148 |
"funcs": ("build_provenance",),
|
| 149 |
"call_style": "ns_q_k",
|
| 150 |
"value_keys": ("trust_value", "provenance_coverage", "lineage_coverage", "score", "value"),
|
| 151 |
-
"adverse": ("unprovenanced", "no-lineage", "no lineage", "unsourced"),
|
| 152 |
},
|
| 153 |
{
|
| 154 |
"key": "contradiction",
|
|
@@ -439,6 +463,168 @@ def _gather_component(spec: dict, q: str, k: int, ns: str = "a11oy") -> dict:
|
|
| 439 |
return base
|
| 440 |
|
| 441 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
# ---------------------------------------------------------------------------
|
| 443 |
# Rollup assembly — pure computation over ONLY the available components. Mints nothing.
|
| 444 |
# ---------------------------------------------------------------------------
|
|
@@ -485,8 +671,16 @@ def _modeled_trust(components: list[dict]) -> float | None:
|
|
| 485 |
def build_rollup(q: str = "", k: int = 12, ns: str = "a11oy") -> dict:
|
| 486 |
"""Gather every brain-honesty component (available ones read VERBATIM, missing ones
|
| 487 |
UNAVAILABLE) and roll the AVAILABLE ones into ONE honest brain-trust verdict."""
|
| 488 |
-
|
| 489 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 490 |
|
| 491 |
available = [c for c in components if c["available"]]
|
| 492 |
unavailable = [c for c in components if not c["available"]]
|
|
@@ -501,7 +695,9 @@ def build_rollup(q: str = "", k: int = 12, ns: str = "a11oy") -> dict:
|
|
| 501 |
for c in available if c["signal"] == SIG_ADVERSE],
|
| 502 |
"min_components_required": MIN_COMPONENTS,
|
| 503 |
}
|
| 504 |
-
trust = _modeled_trust(components)
|
|
|
|
|
|
|
| 505 |
|
| 506 |
return {
|
| 507 |
"ok": True,
|
|
@@ -512,6 +708,14 @@ def build_rollup(q: str = "", k: int = 12, ns: str = "a11oy") -> dict:
|
|
| 512 |
"label": MODELED,
|
| 513 |
"query": q,
|
| 514 |
"k": k,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 515 |
"verdict": verdict,
|
| 516 |
"verdict_reason": reason,
|
| 517 |
"modeled_trust": trust,
|
|
@@ -524,6 +728,7 @@ def build_rollup(q: str = "", k: int = 12, ns: str = "a11oy") -> dict:
|
|
| 524 |
"honesty — advances no detection/fusion/effector/targeting/cueing capability."),
|
| 525 |
"components": components,
|
| 526 |
"summary": summary,
|
|
|
|
| 527 |
"doctrine": {
|
| 528 |
"label_top": MODELED,
|
| 529 |
"locked_proven": LOCKED_COUNT,
|
|
@@ -559,6 +764,7 @@ def _canonical_core(rollup: dict) -> str:
|
|
| 559 |
volatile timestamp), so the digest attests the VERDICT + component evidence, not the clock."""
|
| 560 |
core = {
|
| 561 |
"query": rollup.get("query"),
|
|
|
|
| 562 |
"verdict": rollup.get("verdict"),
|
| 563 |
"modeled_trust": rollup.get("modeled_trust"),
|
| 564 |
"summary": rollup.get("summary"),
|
|
@@ -568,6 +774,10 @@ def _canonical_core(rollup: dict) -> str:
|
|
| 568 |
"adverse_reason": c.get("adverse_reason")}
|
| 569 |
for c in rollup.get("components", [])
|
| 570 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 571 |
}
|
| 572 |
return json.dumps(core, sort_keys=True, separators=(",", ":"), default=str)
|
| 573 |
|
|
@@ -589,6 +799,96 @@ def _content_receipt(rollup: dict) -> dict:
|
|
| 589 |
}
|
| 590 |
|
| 591 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 592 |
# ---------------------------------------------------------------------------
|
| 593 |
# Handlers.
|
| 594 |
# ---------------------------------------------------------------------------
|
|
@@ -615,7 +915,17 @@ def handle_info(ns: str = "a11oy") -> dict:
|
|
| 615 |
"info": f"GET {base}/info",
|
| 616 |
"health": f"GET {base}?q=&k=",
|
| 617 |
"receipt": f"POST {base}/receipt",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 618 |
},
|
|
|
|
| 619 |
"verdicts": list(VERDICTS),
|
| 620 |
"verdict_legend": {
|
| 621 |
TRUSTWORTHY: "enough components available and ALL OK; none UNAVAILABLE",
|
|
@@ -699,6 +1009,17 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 699 |
"""Live brain-trust rollup verdict + per-component value/label/available (pure read)."""
|
| 700 |
return JSONResponse(handle_health(q, k, ns))
|
| 701 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 702 |
async def _brainhealth_receipt(request):
|
| 703 |
"""POST: rollup + UNSIGNED SHA-256 content digest (RECEIPT-ON-WRITE). Reads q/k from the
|
| 704 |
query string when present; the body is otherwise ignored (a pure rollup compute)."""
|
|
@@ -718,6 +1039,7 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 718 |
pass
|
| 719 |
|
| 720 |
rec_path = f"{base}/receipt"
|
|
|
|
| 721 |
add_route = getattr(getattr(app, "router", None), "add_route", None)
|
| 722 |
add_api_route = getattr(app, "add_api_route", None)
|
| 723 |
try:
|
|
@@ -733,7 +1055,50 @@ def register(app, ns: str = "a11oy") -> str:
|
|
| 733 |
file=__import__("sys").stderr)
|
| 734 |
return "brainhealth-wired:2(get-only)"
|
| 735 |
|
| 736 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 737 |
|
| 738 |
|
| 739 |
# ---------------------------------------------------------------------------
|
|
|
|
| 54 |
import hashlib
|
| 55 |
import importlib
|
| 56 |
import json
|
| 57 |
+
import pathlib
|
| 58 |
import re
|
| 59 |
+
import threading
|
| 60 |
+
import time
|
| 61 |
from typing import Any, Callable
|
| 62 |
|
| 63 |
+
import szl_braincorpus as _braincorpus
|
| 64 |
+
|
| 65 |
try: # numpy is allowed; used only for the modeled mean, guarded so a missing wheel is honest.
|
| 66 |
import numpy as _np
|
| 67 |
_HAVE_NUMPY = True
|
|
|
|
| 97 |
UNTRUSTWORTHY = "UNTRUSTWORTHY"
|
| 98 |
INSUFFICIENT_SIGNAL = "INSUFFICIENT-SIGNAL"
|
| 99 |
|
| 100 |
+
# Operational readiness is deliberately separate from epistemic/query trust. A service can
|
| 101 |
+
# load its index and expose every honesty component while a particular question still needs to
|
| 102 |
+
# abstain. Conflating these two states made the blank dashboard query look like a failed brain.
|
| 103 |
+
SERVICE_READY = "READY"
|
| 104 |
+
SERVICE_DEGRADED = "DEGRADED"
|
| 105 |
+
QUERY_EVALUATED = "EVALUATED"
|
| 106 |
+
QUERY_NOT_EVALUATED = "NOT-EVALUATED"
|
| 107 |
+
|
| 108 |
+
_ROOT = pathlib.Path(__file__).resolve().parent
|
| 109 |
+
|
| 110 |
+
_REFRESH_LOCK = threading.Lock()
|
| 111 |
+
_REFRESH_COOLDOWN_SECONDS = 5.0
|
| 112 |
+
_LAST_REFRESH_MONOTONIC = 0.0
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def _client_is_loopback(host: str | None) -> bool:
|
| 116 |
+
"""Fail-closed client check for the local-only cache rebuild endpoint."""
|
| 117 |
+
return str(host or "").strip().lower() in {"127.0.0.1", "::1", "localhost", "testclient"}
|
| 118 |
+
|
| 119 |
VERDICTS = (TRUSTWORTHY, DEGRADED, UNTRUSTWORTHY, INSUFFICIENT_SIGNAL)
|
| 120 |
|
| 121 |
# Minimum available components required to render a confident verdict; below this the honest
|
|
|
|
| 172 |
"funcs": ("build_provenance",),
|
| 173 |
"call_style": "ns_q_k",
|
| 174 |
"value_keys": ("trust_value", "provenance_coverage", "lineage_coverage", "score", "value"),
|
| 175 |
+
"adverse": ("unprovenanced", "untraceable", "no-lineage", "no lineage", "unsourced"),
|
| 176 |
},
|
| 177 |
{
|
| 178 |
"key": "contradiction",
|
|
|
|
| 463 |
return base
|
| 464 |
|
| 465 |
|
| 466 |
+
def _component_module_readiness() -> list[dict]:
|
| 467 |
+
"""Probe import/entrypoint readiness without running a query or inventing query evidence."""
|
| 468 |
+
checks = []
|
| 469 |
+
for spec in COMPONENTS:
|
| 470 |
+
fn = _resolve_callable(spec)
|
| 471 |
+
checks.append({
|
| 472 |
+
"key": spec["key"],
|
| 473 |
+
"module": spec["module"],
|
| 474 |
+
"ready": callable(fn),
|
| 475 |
+
"entrypoint": spec["funcs"][0],
|
| 476 |
+
})
|
| 477 |
+
return checks
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
def _source_snapshot_metadata(ns: str = "a11oy") -> dict:
|
| 481 |
+
"""Small, source-authored snapshot manifest; never substitutes request time for capture time."""
|
| 482 |
+
try:
|
| 483 |
+
import a11oy_brain_graph as graph_module
|
| 484 |
+
import szl_brain_api as brain_api
|
| 485 |
+
|
| 486 |
+
graph = graph_module.get_brain_graph(ns)
|
| 487 |
+
index = brain_api.get_index(ns)
|
| 488 |
+
sources = graph.get("sources") if isinstance(graph.get("sources"), dict) else {}
|
| 489 |
+
repos = sources.get("repos") if isinstance(sources.get("repos"), dict) else {}
|
| 490 |
+
harvest = sources.get("harvest") if isinstance(sources.get("harvest"), dict) else {}
|
| 491 |
+
return {
|
| 492 |
+
"available": True,
|
| 493 |
+
"label": graph.get("label", MODELED),
|
| 494 |
+
"graph_generated_at": graph.get("generated"),
|
| 495 |
+
"graph_content_hash": getattr(index, "content_hash", None),
|
| 496 |
+
"node_count": graph.get("node_count"),
|
| 497 |
+
"link_count": graph.get("link_count"),
|
| 498 |
+
"distinct_artifacts": graph.get("distinct_artifacts"),
|
| 499 |
+
"sources": {
|
| 500 |
+
"surfaces": sources.get("surfaces"),
|
| 501 |
+
"formulas": sources.get("formulas"),
|
| 502 |
+
"repos": repos,
|
| 503 |
+
"topics": sources.get("topics"),
|
| 504 |
+
"harvest": harvest,
|
| 505 |
+
},
|
| 506 |
+
"capture_evidence": {
|
| 507 |
+
"repo_snapshot_captured": repos.get("captured"),
|
| 508 |
+
"repo_snapshot_source": repos.get("source"),
|
| 509 |
+
"harvest_files": list(harvest.get("files") or []),
|
| 510 |
+
"harvest_source": harvest.get("source"),
|
| 511 |
+
},
|
| 512 |
+
"freshness_rule": (
|
| 513 |
+
"only source-provided captured_at/harvested_at values count as recency; "
|
| 514 |
+
"graph_generated_at is cache-build time and is never treated as source freshness"
|
| 515 |
+
),
|
| 516 |
+
"refresh_scope": "bounded committed local sources; no network, no source-date rewrite",
|
| 517 |
+
}
|
| 518 |
+
except Exception as exc:
|
| 519 |
+
return {
|
| 520 |
+
"available": False,
|
| 521 |
+
"label": UNAVAILABLE,
|
| 522 |
+
"error": str(exc)[:200],
|
| 523 |
+
"freshness_rule": "no source timestamp fabricated while snapshot is unavailable",
|
| 524 |
+
"refresh_scope": "bounded committed local sources; no network, no source-date rewrite",
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
def build_corpus_source_contract() -> dict:
|
| 529 |
+
"""Return the bounded content-addressed corpus admission status (pure read)."""
|
| 530 |
+
return _braincorpus.build_corpus_status(_ROOT)
|
| 531 |
+
|
| 532 |
+
|
| 533 |
+
def _service_readiness(ns: str = "a11oy", snapshot: dict | None = None) -> dict:
|
| 534 |
+
"""Operational/service readiness only. It is never a synonym for query trust."""
|
| 535 |
+
module_checks = _component_module_readiness()
|
| 536 |
+
snapshot = snapshot if isinstance(snapshot, dict) else _source_snapshot_metadata(ns)
|
| 537 |
+
modules_ready = all(c["ready"] for c in module_checks)
|
| 538 |
+
index_ready = bool(snapshot.get("available") and snapshot.get("graph_content_hash")
|
| 539 |
+
and isinstance(snapshot.get("node_count"), int)
|
| 540 |
+
and snapshot.get("node_count") > 0)
|
| 541 |
+
operational = modules_ready and index_ready
|
| 542 |
+
return {
|
| 543 |
+
"status": SERVICE_READY if operational else SERVICE_DEGRADED,
|
| 544 |
+
"operational": operational,
|
| 545 |
+
"query_trust_equivalent": False,
|
| 546 |
+
"checks": {
|
| 547 |
+
"brain_index_readable": index_ready,
|
| 548 |
+
"honesty_components_loadable": modules_ready,
|
| 549 |
+
"component_modules": module_checks,
|
| 550 |
+
},
|
| 551 |
+
"note": (
|
| 552 |
+
"READY means the local graph/index and honesty evaluators can serve requests; it does "
|
| 553 |
+
"not mean any query is trustworthy. Query trust remains a separate evidence verdict."
|
| 554 |
+
),
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
|
| 558 |
+
def _remediation_plan(components: list[dict], query_evaluated: bool, ns: str) -> list[dict]:
|
| 559 |
+
"""Return concrete next actions for observed gaps; actions never change verdicts by fiat."""
|
| 560 |
+
base = f"/api/{ns}/v1/brain/health"
|
| 561 |
+
if not query_evaluated:
|
| 562 |
+
return [{
|
| 563 |
+
"component": "query",
|
| 564 |
+
"action": "submit a non-empty q parameter to run grounding/provenance/conflict/uncertainty",
|
| 565 |
+
"endpoint": f"GET {base}?q=<question>&k=12",
|
| 566 |
+
"effect_on_trust": "none until evidence is evaluated",
|
| 567 |
+
}]
|
| 568 |
+
|
| 569 |
+
actions = []
|
| 570 |
+
adverse = {c.get("key"): c.get("adverse_reason") for c in components
|
| 571 |
+
if c.get("signal") == SIG_ADVERSE}
|
| 572 |
+
if "freshness" in adverse:
|
| 573 |
+
actions.append({
|
| 574 |
+
"component": "freshness",
|
| 575 |
+
"action": (
|
| 576 |
+
"reindex the bounded committed local sources, then replace stale/undated source "
|
| 577 |
+
"snapshots only through a separately reviewed harvest carrying real capture times"
|
| 578 |
+
),
|
| 579 |
+
"endpoint": f"POST {base}/refresh",
|
| 580 |
+
"limitation": (
|
| 581 |
+
"local reindex clears caches but cannot make old evidence fresh or rewrite capture times"
|
| 582 |
+
),
|
| 583 |
+
})
|
| 584 |
+
if "grounding" in adverse:
|
| 585 |
+
actions.append({
|
| 586 |
+
"component": "grounding",
|
| 587 |
+
"action": "narrow the query or ingest a cited local source that directly covers its terms",
|
| 588 |
+
"effect_on_trust": "re-evaluate; no automatic upgrade",
|
| 589 |
+
})
|
| 590 |
+
if "provenance" in adverse:
|
| 591 |
+
actions.append({
|
| 592 |
+
"component": "provenance",
|
| 593 |
+
"action": "attach source/url and an honest label to every supporting node, then reindex",
|
| 594 |
+
"effect_on_trust": "re-evaluate; no automatic upgrade",
|
| 595 |
+
})
|
| 596 |
+
if "contradiction" in adverse:
|
| 597 |
+
actions.append({
|
| 598 |
+
"component": "contradiction",
|
| 599 |
+
"action": "inspect the reported conflict pairs; resolve sources or narrow the claim scope",
|
| 600 |
+
"effect_on_trust": "re-evaluate; conflicts remain adverse until evidence changes",
|
| 601 |
+
})
|
| 602 |
+
if "uncertainty" in adverse:
|
| 603 |
+
actions.append({
|
| 604 |
+
"component": "uncertainty",
|
| 605 |
+
"action": "narrow the question and require a more concentrated, source-cited retrieval",
|
| 606 |
+
"effect_on_trust": "re-evaluate; abstention remains active until uncertainty falls",
|
| 607 |
+
})
|
| 608 |
+
return actions
|
| 609 |
+
|
| 610 |
+
|
| 611 |
+
def _unevaluated_components() -> list[dict]:
|
| 612 |
+
checks = {c["key"]: c for c in _component_module_readiness()}
|
| 613 |
+
return [{
|
| 614 |
+
"key": spec["key"],
|
| 615 |
+
"title": spec["title"],
|
| 616 |
+
"module": spec["module"],
|
| 617 |
+
"available": False,
|
| 618 |
+
"service_available": bool(checks[spec["key"]]["ready"]),
|
| 619 |
+
"label": UNAVAILABLE,
|
| 620 |
+
"value": None,
|
| 621 |
+
"signal": None,
|
| 622 |
+
"adverse_reason": None,
|
| 623 |
+
"evaluation_status": QUERY_NOT_EVALUATED,
|
| 624 |
+
"note": "no query was supplied; component was not invoked and no query evidence was fabricated",
|
| 625 |
+
} for spec in COMPONENTS]
|
| 626 |
+
|
| 627 |
+
|
| 628 |
# ---------------------------------------------------------------------------
|
| 629 |
# Rollup assembly — pure computation over ONLY the available components. Mints nothing.
|
| 630 |
# ---------------------------------------------------------------------------
|
|
|
|
| 671 |
def build_rollup(q: str = "", k: int = 12, ns: str = "a11oy") -> dict:
|
| 672 |
"""Gather every brain-honesty component (available ones read VERBATIM, missing ones
|
| 673 |
UNAVAILABLE) and roll the AVAILABLE ones into ONE honest brain-trust verdict."""
|
| 674 |
+
q = (q or "").strip()
|
| 675 |
+
query_evaluated = bool(q)
|
| 676 |
+
if query_evaluated:
|
| 677 |
+
components = [_gather_component(spec, q, k, ns=ns) for spec in COMPONENTS]
|
| 678 |
+
verdict, reason = _decide_verdict(components)
|
| 679 |
+
else:
|
| 680 |
+
components = _unevaluated_components()
|
| 681 |
+
verdict = INSUFFICIENT_SIGNAL
|
| 682 |
+
reason = ("no query supplied; epistemic trust was NOT EVALUATED. Operational readiness "
|
| 683 |
+
"is reported separately and is never promoted into a query-trust verdict")
|
| 684 |
|
| 685 |
available = [c for c in components if c["available"]]
|
| 686 |
unavailable = [c for c in components if not c["available"]]
|
|
|
|
| 695 |
for c in available if c["signal"] == SIG_ADVERSE],
|
| 696 |
"min_components_required": MIN_COMPONENTS,
|
| 697 |
}
|
| 698 |
+
trust = _modeled_trust(components) if query_evaluated else None
|
| 699 |
+
snapshot = _source_snapshot_metadata(ns)
|
| 700 |
+
readiness = _service_readiness(ns, snapshot=snapshot)
|
| 701 |
|
| 702 |
return {
|
| 703 |
"ok": True,
|
|
|
|
| 708 |
"label": MODELED,
|
| 709 |
"query": q,
|
| 710 |
"k": k,
|
| 711 |
+
"query_assessment": {
|
| 712 |
+
"status": QUERY_EVALUATED if query_evaluated else QUERY_NOT_EVALUATED,
|
| 713 |
+
"evaluated": query_evaluated,
|
| 714 |
+
"note": ("component evidence evaluated for this query" if query_evaluated else
|
| 715 |
+
"blank q is a service-status view only; no answer trust was inferred"),
|
| 716 |
+
},
|
| 717 |
+
"service_readiness": readiness,
|
| 718 |
+
"source_snapshot": snapshot,
|
| 719 |
"verdict": verdict,
|
| 720 |
"verdict_reason": reason,
|
| 721 |
"modeled_trust": trust,
|
|
|
|
| 728 |
"honesty — advances no detection/fusion/effector/targeting/cueing capability."),
|
| 729 |
"components": components,
|
| 730 |
"summary": summary,
|
| 731 |
+
"remediation": _remediation_plan(components, query_evaluated, ns),
|
| 732 |
"doctrine": {
|
| 733 |
"label_top": MODELED,
|
| 734 |
"locked_proven": LOCKED_COUNT,
|
|
|
|
| 764 |
volatile timestamp), so the digest attests the VERDICT + component evidence, not the clock."""
|
| 765 |
core = {
|
| 766 |
"query": rollup.get("query"),
|
| 767 |
+
"query_assessment": rollup.get("query_assessment"),
|
| 768 |
"verdict": rollup.get("verdict"),
|
| 769 |
"modeled_trust": rollup.get("modeled_trust"),
|
| 770 |
"summary": rollup.get("summary"),
|
|
|
|
| 774 |
"adverse_reason": c.get("adverse_reason")}
|
| 775 |
for c in rollup.get("components", [])
|
| 776 |
],
|
| 777 |
+
"source_snapshot": {
|
| 778 |
+
"graph_content_hash": (rollup.get("source_snapshot") or {}).get("graph_content_hash"),
|
| 779 |
+
"capture_evidence": (rollup.get("source_snapshot") or {}).get("capture_evidence"),
|
| 780 |
+
},
|
| 781 |
}
|
| 782 |
return json.dumps(core, sort_keys=True, separators=(",", ":"), default=str)
|
| 783 |
|
|
|
|
| 799 |
}
|
| 800 |
|
| 801 |
|
| 802 |
+
def _refresh_receipt(core: dict) -> dict:
|
| 803 |
+
canonical = json.dumps(core, sort_keys=True, separators=(",", ":"), default=str)
|
| 804 |
+
return {
|
| 805 |
+
"kind": "szl.brainhealth.bounded-local-reindex",
|
| 806 |
+
"algorithm": "sha256",
|
| 807 |
+
"content_sha256": hashlib.sha256(canonical.encode("utf-8")).hexdigest(),
|
| 808 |
+
"signed": False,
|
| 809 |
+
"mode": "UNSIGNED-CONTENT-DIGEST",
|
| 810 |
+
"receipt_on": "write (POST refresh)",
|
| 811 |
+
"note": (
|
| 812 |
+
"unsigned digest of the bounded local reindex result; no source timestamps were "
|
| 813 |
+
"rewritten and no signature was fabricated"
|
| 814 |
+
),
|
| 815 |
+
"computed_at": _now_iso(),
|
| 816 |
+
}
|
| 817 |
+
|
| 818 |
+
|
| 819 |
+
def handle_refresh(ns: str = "a11oy") -> dict:
|
| 820 |
+
"""Rebuild only the in-process graph/index from committed local sources.
|
| 821 |
+
|
| 822 |
+
This is intentionally not a network harvest and cannot make stale evidence fresh. It is a
|
| 823 |
+
bounded cache/index write with a receipt so operators can distinguish "reindexed" from
|
| 824 |
+
"source evidence updated".
|
| 825 |
+
"""
|
| 826 |
+
global _LAST_REFRESH_MONOTONIC
|
| 827 |
+
if not _REFRESH_LOCK.acquire(blocking=False):
|
| 828 |
+
return {
|
| 829 |
+
"ok": False, "endpoint": "brain/health/refresh", "label": UNAVAILABLE,
|
| 830 |
+
"outcome": "REINDEX-IN-PROGRESS", "retry_after_seconds": _REFRESH_COOLDOWN_SECONDS,
|
| 831 |
+
"source_freshness_changed": False, "receipt": None,
|
| 832 |
+
}
|
| 833 |
+
now = time.monotonic()
|
| 834 |
+
if _LAST_REFRESH_MONOTONIC and now - _LAST_REFRESH_MONOTONIC < _REFRESH_COOLDOWN_SECONDS:
|
| 835 |
+
retry = round(_REFRESH_COOLDOWN_SECONDS - (now - _LAST_REFRESH_MONOTONIC), 3)
|
| 836 |
+
_REFRESH_LOCK.release()
|
| 837 |
+
return {
|
| 838 |
+
"ok": False, "endpoint": "brain/health/refresh", "label": UNAVAILABLE,
|
| 839 |
+
"outcome": "REINDEX-COOLDOWN", "retry_after_seconds": retry,
|
| 840 |
+
"source_freshness_changed": False, "receipt": None,
|
| 841 |
+
}
|
| 842 |
+
before = _source_snapshot_metadata(ns)
|
| 843 |
+
try:
|
| 844 |
+
import szl_brain_api as brain_api
|
| 845 |
+
|
| 846 |
+
# get_index(refresh=True) refreshes the graph exactly once and rebuilds the index.
|
| 847 |
+
brain_api.get_index(ns, refresh=True)
|
| 848 |
+
after = _source_snapshot_metadata(ns)
|
| 849 |
+
core = {
|
| 850 |
+
"scope": "BOUNDED-COMMITTED-LOCAL-SOURCES",
|
| 851 |
+
"network_access": False,
|
| 852 |
+
"source_timestamps_rewritten": False,
|
| 853 |
+
"before_content_hash": before.get("graph_content_hash"),
|
| 854 |
+
"after_content_hash": after.get("graph_content_hash"),
|
| 855 |
+
"node_count": after.get("node_count"),
|
| 856 |
+
"link_count": after.get("link_count"),
|
| 857 |
+
"capture_evidence": after.get("capture_evidence"),
|
| 858 |
+
}
|
| 859 |
+
return {
|
| 860 |
+
"ok": True,
|
| 861 |
+
"endpoint": "brain/health/refresh",
|
| 862 |
+
"label": MODELED,
|
| 863 |
+
"outcome": "REINDEXED",
|
| 864 |
+
"changed": core["before_content_hash"] != core["after_content_hash"],
|
| 865 |
+
"source_freshness_changed": False,
|
| 866 |
+
"before": before,
|
| 867 |
+
"after": after,
|
| 868 |
+
"receipt": _refresh_receipt(core),
|
| 869 |
+
"note": (
|
| 870 |
+
"local caches/index rebuilt from committed bounded sources. This does not refresh "
|
| 871 |
+
"old capture dates; update source snapshots through a reviewed harvest if stale."
|
| 872 |
+
),
|
| 873 |
+
"timestamp_utc": _now_iso(),
|
| 874 |
+
}
|
| 875 |
+
except Exception as exc:
|
| 876 |
+
return {
|
| 877 |
+
"ok": False,
|
| 878 |
+
"endpoint": "brain/health/refresh",
|
| 879 |
+
"label": UNAVAILABLE,
|
| 880 |
+
"outcome": "REINDEX-FAILED",
|
| 881 |
+
"source_freshness_changed": False,
|
| 882 |
+
"error": str(exc)[:200],
|
| 883 |
+
"receipt": None,
|
| 884 |
+
"note": "no source timestamps changed and no receipt minted over a failed reindex",
|
| 885 |
+
"timestamp_utc": _now_iso(),
|
| 886 |
+
}
|
| 887 |
+
finally:
|
| 888 |
+
_LAST_REFRESH_MONOTONIC = time.monotonic()
|
| 889 |
+
_REFRESH_LOCK.release()
|
| 890 |
+
|
| 891 |
+
|
| 892 |
# ---------------------------------------------------------------------------
|
| 893 |
# Handlers.
|
| 894 |
# ---------------------------------------------------------------------------
|
|
|
|
| 915 |
"info": f"GET {base}/info",
|
| 916 |
"health": f"GET {base}?q=&k=",
|
| 917 |
"receipt": f"POST {base}/receipt",
|
| 918 |
+
"bounded_local_reindex": f"POST {base}/refresh",
|
| 919 |
+
"corpus_sources": f"GET {base}/corpus-sources",
|
| 920 |
+
"corpus_sources_info": f"GET {base}/corpus-sources/info",
|
| 921 |
+
},
|
| 922 |
+
"state_separation": {
|
| 923 |
+
"service_readiness": "can the graph/index and evaluators serve a request?",
|
| 924 |
+
"query_trust": "does the evidence support this specific non-empty query?",
|
| 925 |
+
"invariant": "service READY never promotes query trust",
|
| 926 |
+
"empty_query": QUERY_NOT_EVALUATED,
|
| 927 |
},
|
| 928 |
+
"source_snapshot": _source_snapshot_metadata(ns),
|
| 929 |
"verdicts": list(VERDICTS),
|
| 930 |
"verdict_legend": {
|
| 931 |
TRUSTWORTHY: "enough components available and ALL OK; none UNAVAILABLE",
|
|
|
|
| 1009 |
"""Live brain-trust rollup verdict + per-component value/label/available (pure read)."""
|
| 1010 |
return JSONResponse(handle_health(q, k, ns))
|
| 1011 |
|
| 1012 |
+
@app.get(f"{base}/corpus-sources")
|
| 1013 |
+
def _brainhealth_corpus_sources():
|
| 1014 |
+
"""Versioned local evidence manifests under the no-uplift proof lattice."""
|
| 1015 |
+
return JSONResponse(build_corpus_source_contract())
|
| 1016 |
+
|
| 1017 |
+
@app.get(f"{base}/corpus-sources/info")
|
| 1018 |
+
def _brainhealth_corpus_sources_info():
|
| 1019 |
+
"""Static, side-effect-free content-addressed corpus admission contract."""
|
| 1020 |
+
return JSONResponse({"ok": True, "endpoint": "brain/health/corpus-sources/info",
|
| 1021 |
+
**_braincorpus.info()})
|
| 1022 |
+
|
| 1023 |
async def _brainhealth_receipt(request):
|
| 1024 |
"""POST: rollup + UNSIGNED SHA-256 content digest (RECEIPT-ON-WRITE). Reads q/k from the
|
| 1025 |
query string when present; the body is otherwise ignored (a pure rollup compute)."""
|
|
|
|
| 1039 |
pass
|
| 1040 |
|
| 1041 |
rec_path = f"{base}/receipt"
|
| 1042 |
+
refresh_path = f"{base}/refresh"
|
| 1043 |
add_route = getattr(getattr(app, "router", None), "add_route", None)
|
| 1044 |
add_api_route = getattr(app, "add_api_route", None)
|
| 1045 |
try:
|
|
|
|
| 1055 |
file=__import__("sys").stderr)
|
| 1056 |
return "brainhealth-wired:2(get-only)"
|
| 1057 |
|
| 1058 |
+
async def _brainhealth_refresh(request):
|
| 1059 |
+
"""POST: bounded local cache/index rebuild with an unsigned result receipt."""
|
| 1060 |
+
client = getattr(request, "client", None)
|
| 1061 |
+
host = getattr(client, "host", None)
|
| 1062 |
+
if not _client_is_loopback(host):
|
| 1063 |
+
return JSONResponse({
|
| 1064 |
+
"ok": False,
|
| 1065 |
+
"endpoint": "brain/health/refresh",
|
| 1066 |
+
"label": UNAVAILABLE,
|
| 1067 |
+
"outcome": "LOCAL-CLIENT-REQUIRED",
|
| 1068 |
+
"source_freshness_changed": False,
|
| 1069 |
+
"receipt": None,
|
| 1070 |
+
"note": "bounded local reindex rejects non-loopback clients; no auth bypass",
|
| 1071 |
+
}, status_code=403)
|
| 1072 |
+
result = handle_refresh(ns)
|
| 1073 |
+
status = 200
|
| 1074 |
+
if result.get("outcome") == "REINDEX-IN-PROGRESS":
|
| 1075 |
+
status = 409
|
| 1076 |
+
elif result.get("outcome") == "REINDEX-COOLDOWN":
|
| 1077 |
+
status = 429
|
| 1078 |
+
elif not result.get("ok"):
|
| 1079 |
+
status = 503
|
| 1080 |
+
return JSONResponse(result, status_code=status)
|
| 1081 |
+
|
| 1082 |
+
try:
|
| 1083 |
+
import fastapi as _fastapi
|
| 1084 |
+
_brainhealth_refresh.__annotations__["request"] = _fastapi.Request
|
| 1085 |
+
except Exception: # noqa: BLE001
|
| 1086 |
+
pass
|
| 1087 |
+
|
| 1088 |
+
try:
|
| 1089 |
+
if callable(add_route):
|
| 1090 |
+
app.router.add_route(refresh_path, _brainhealth_refresh, methods=["POST"])
|
| 1091 |
+
elif callable(add_api_route):
|
| 1092 |
+
app.add_api_route(refresh_path, _brainhealth_refresh, methods=["POST"])
|
| 1093 |
+
else: # pragma: no cover
|
| 1094 |
+
from starlette.routing import Route
|
| 1095 |
+
app.router.routes.append(Route(refresh_path, _brainhealth_refresh, methods=["POST"]))
|
| 1096 |
+
except Exception as exc: # additive register must never break boot
|
| 1097 |
+
print(f"[{ns}] brainhealth refresh POST route NOT wired (guarded): {exc!r}",
|
| 1098 |
+
file=__import__("sys").stderr)
|
| 1099 |
+
return "brainhealth-wired:3(no-refresh)"
|
| 1100 |
+
|
| 1101 |
+
return "brainhealth-wired:5"
|
| 1102 |
|
| 1103 |
|
| 1104 |
# ---------------------------------------------------------------------------
|
|
@@ -473,4 +473,3 @@ def info() -> dict[str, Any]:
|
|
| 473 |
],
|
| 474 |
"not_implemented_here": ["HTTP registration", "persistence", "signing", "effectors"],
|
| 475 |
}
|
| 476 |
-
|
|
|
|
| 473 |
],
|
| 474 |
"not_implemented_here": ["HTTP registration", "persistence", "signing", "effectors"],
|
| 475 |
}
|
|
|
|
@@ -0,0 +1,727 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 3 |
+
# (c) 2026 Lutar, Stephen P. - SZL Holdings - ORCID 0009-0001-0110-4173
|
| 4 |
+
"""Fail-closed formal-conjecture attempt and kernel-receipt ledger.
|
| 5 |
+
|
| 6 |
+
Taxonomy home: services/provenance. This module does not execute a prover. It
|
| 7 |
+
stores bounded declarations and formal artifacts, then accepts only a DSSE
|
| 8 |
+
kernel-result receipt that verifies against the published SZL cosign public
|
| 9 |
+
key and binds the exact server-computed statement and artifact hashes.
|
| 10 |
+
|
| 11 |
+
``KERNEL_ACCEPTED`` means only that the configured external Lean 4 checker
|
| 12 |
+
reported exit code zero with no sorries or unsafe declarations. It does not
|
| 13 |
+
promote a conjecture, add a locked formula, establish novelty, or authorize a
|
| 14 |
+
publication claim. Reads never mint receipts; every successful write appends
|
| 15 |
+
one hash-chained, honestly unsigned DSSE-shaped Khipu event.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
import base64
|
| 19 |
+
import binascii
|
| 20 |
+
import datetime
|
| 21 |
+
import hashlib
|
| 22 |
+
import json
|
| 23 |
+
import os
|
| 24 |
+
import re
|
| 25 |
+
import threading
|
| 26 |
+
from pathlib import Path
|
| 27 |
+
from typing import Any, Mapping
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
ATTEMPT_SCHEMA = "szl.formal-conjecture-attempt/v1"
|
| 31 |
+
KERNEL_SCHEMA = "szl.formal-kernel-result/v1"
|
| 32 |
+
KERNEL_PAYLOAD_TYPE = "application/vnd.szl.formal-kernel-result+json"
|
| 33 |
+
LOCAL_PAYLOAD_TYPE = "application/vnd.szl.khipu+json"
|
| 34 |
+
|
| 35 |
+
DECLARED = "DECLARED"
|
| 36 |
+
KERNEL_UNCHECKED = "KERNEL_UNCHECKED"
|
| 37 |
+
KERNEL_ACCEPTED = "KERNEL_ACCEPTED"
|
| 38 |
+
KERNEL_REJECTED = "KERNEL_REJECTED"
|
| 39 |
+
UNAVAILABLE = "UNAVAILABLE"
|
| 40 |
+
STATES = (DECLARED, KERNEL_UNCHECKED, KERNEL_ACCEPTED, KERNEL_REJECTED, UNAVAILABLE)
|
| 41 |
+
|
| 42 |
+
MAX_BODY_BYTES = 384 * 1024
|
| 43 |
+
MAX_STATEMENT_CHARS = 32 * 1024
|
| 44 |
+
MAX_ARTIFACT_CHARS = 256 * 1024
|
| 45 |
+
MAX_TITLE_CHARS = 256
|
| 46 |
+
MAX_BRAIN_REFS = 64
|
| 47 |
+
MAX_EVENTS = 2048
|
| 48 |
+
MAX_LEDGER_BYTES = 8 * 1024 * 1024
|
| 49 |
+
GENESIS = "0" * 64
|
| 50 |
+
LOCKED_SET = ("F1", "F4", "F7", "F11", "F12", "F18", "F19", "F22")
|
| 51 |
+
ARTIFACT_FORMATS = ("LEAN4", "COQ", "ISABELLE", "TEXT")
|
| 52 |
+
SOURCE_KINDS = ("OPERATOR_DECLARED", "CONJECTURE_FACTORY_CACHE")
|
| 53 |
+
|
| 54 |
+
_STATE_PATH = Path(
|
| 55 |
+
os.environ.get(
|
| 56 |
+
"A11OY_FORMAL_CONJECTURE_LAB_PATH",
|
| 57 |
+
str(Path(__file__).resolve().parent / ".a11oy-state" / "formal-conjecture-lab.jsonl"),
|
| 58 |
+
)
|
| 59 |
+
)
|
| 60 |
+
_WRITE_LOCK = threading.RLock()
|
| 61 |
+
_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$")
|
| 62 |
+
_HEX64_RE = re.compile(r"^[0-9a-f]{64}$")
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
class ContractError(ValueError):
|
| 66 |
+
"""The caller supplied a malformed or hidden-field-bearing contract."""
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
class StateConflict(RuntimeError):
|
| 70 |
+
"""The requested transition conflicts with the recorded attempt state."""
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
class LabUnavailable(RuntimeError):
|
| 74 |
+
"""A required local integrity or public-key verification boundary is absent."""
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def _now() -> str:
|
| 78 |
+
return datetime.datetime.now(datetime.timezone.utc).isoformat()
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def _canonical_bytes(value: Any) -> bytes:
|
| 82 |
+
return json.dumps(
|
| 83 |
+
value, sort_keys=True, separators=(",", ":"), ensure_ascii=False, allow_nan=False
|
| 84 |
+
).encode("utf-8")
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def _sha256(value: Any) -> str:
|
| 88 |
+
raw = value.encode("utf-8") if isinstance(value, str) else _canonical_bytes(value)
|
| 89 |
+
return hashlib.sha256(raw).hexdigest()
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def _sha3(value: Any) -> str:
|
| 93 |
+
return hashlib.sha3_256(_canonical_bytes(value)).hexdigest()
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def _mapping(value: Any, name: str) -> Mapping[str, Any]:
|
| 97 |
+
if not isinstance(value, Mapping):
|
| 98 |
+
raise ContractError(f"{name} must be one JSON object")
|
| 99 |
+
return value
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def _strict_keys(value: Mapping[str, Any], expected: set[str], name: str) -> None:
|
| 103 |
+
actual = set(value)
|
| 104 |
+
if actual != expected:
|
| 105 |
+
raise ContractError(
|
| 106 |
+
f"{name} fields must be exactly {sorted(expected)}; got {sorted(actual)}"
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def _text(value: Any, name: str, maximum: int) -> str:
|
| 111 |
+
if not isinstance(value, str) or not value.strip():
|
| 112 |
+
raise ContractError(f"{name} must be a non-empty string")
|
| 113 |
+
clean = value.strip()
|
| 114 |
+
if len(clean) > maximum:
|
| 115 |
+
raise ContractError(f"{name} exceeds {maximum} characters")
|
| 116 |
+
if "\x00" in clean:
|
| 117 |
+
raise ContractError(f"{name} contains a NUL byte")
|
| 118 |
+
return clean
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def _hex64(value: Any, name: str) -> str:
|
| 122 |
+
if not isinstance(value, str) or not _HEX64_RE.fullmatch(value):
|
| 123 |
+
raise ContractError(f"{name} must be one lowercase SHA-256 hex digest")
|
| 124 |
+
return value
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def _parse_brain_refs(value: Any) -> list[str]:
|
| 128 |
+
if not isinstance(value, list) or len(value) > MAX_BRAIN_REFS:
|
| 129 |
+
raise ContractError(f"brain_node_ids must be an array of at most {MAX_BRAIN_REFS} ids")
|
| 130 |
+
refs: list[str] = []
|
| 131 |
+
for index, item in enumerate(value):
|
| 132 |
+
ref = _text(item, f"brain_node_ids[{index}]", 256)
|
| 133 |
+
if ref in refs:
|
| 134 |
+
raise ContractError("brain_node_ids must not contain duplicates")
|
| 135 |
+
refs.append(ref)
|
| 136 |
+
return refs
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def _factory_crosscheck(conjecture_id: str, title: str, statement: str) -> dict[str, Any]:
|
| 140 |
+
"""Cross-check only the on-disk factory cache; this never performs a fetch."""
|
| 141 |
+
try:
|
| 142 |
+
import szl_conjecture_factory
|
| 143 |
+
|
| 144 |
+
item = szl_conjecture_factory.load_conjecture(conjecture_id, force_refresh=False)
|
| 145 |
+
except Exception as exc:
|
| 146 |
+
raise LabUnavailable(
|
| 147 |
+
f"conjecture factory cache unavailable ({type(exc).__name__}); no source match assumed"
|
| 148 |
+
) from exc
|
| 149 |
+
if item is None:
|
| 150 |
+
raise LabUnavailable("conjecture id is absent from the local factory cache")
|
| 151 |
+
if str(item.get("statement") or "").strip() != statement:
|
| 152 |
+
raise ContractError("statement does not exactly match the cached conjecture statement")
|
| 153 |
+
cached_title = str(item.get("title") or "").strip()
|
| 154 |
+
if cached_title and cached_title != title:
|
| 155 |
+
raise ContractError("title does not exactly match the cached conjecture title")
|
| 156 |
+
return {
|
| 157 |
+
"factory_receipt_id": item.get("receipt", {}).get("receipt_id"),
|
| 158 |
+
"factory_envelope_status": item.get("_envelope_status"),
|
| 159 |
+
"factory_statement_sha256": _sha256(statement),
|
| 160 |
+
"crosscheck": "EXACT_LOCAL_CACHE_MATCH",
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
def normalize_attempt_request(request: Mapping[str, Any]) -> dict[str, Any]:
|
| 165 |
+
obj = _mapping(request, "attempt")
|
| 166 |
+
expected = {
|
| 167 |
+
"schema_version", "source_kind", "conjecture_id", "title", "statement",
|
| 168 |
+
"artifact", "artifact_format", "brain_node_ids",
|
| 169 |
+
}
|
| 170 |
+
_strict_keys(obj, expected, "attempt")
|
| 171 |
+
if obj.get("schema_version") != ATTEMPT_SCHEMA:
|
| 172 |
+
raise ContractError(f"schema_version must be {ATTEMPT_SCHEMA}")
|
| 173 |
+
source_kind = _text(obj.get("source_kind"), "source_kind", 64)
|
| 174 |
+
if source_kind not in SOURCE_KINDS:
|
| 175 |
+
raise ContractError(f"source_kind must be one of {SOURCE_KINDS}")
|
| 176 |
+
conjecture_id = _text(obj.get("conjecture_id"), "conjecture_id", 128)
|
| 177 |
+
if not _ID_RE.fullmatch(conjecture_id):
|
| 178 |
+
raise ContractError("conjecture_id contains unsupported characters")
|
| 179 |
+
title = _text(obj.get("title"), "title", MAX_TITLE_CHARS)
|
| 180 |
+
statement = _text(obj.get("statement"), "statement", MAX_STATEMENT_CHARS)
|
| 181 |
+
artifact_value = obj.get("artifact")
|
| 182 |
+
if artifact_value is None:
|
| 183 |
+
artifact = None
|
| 184 |
+
elif isinstance(artifact_value, str):
|
| 185 |
+
artifact = artifact_value
|
| 186 |
+
if len(artifact) > MAX_ARTIFACT_CHARS:
|
| 187 |
+
raise ContractError(f"artifact exceeds {MAX_ARTIFACT_CHARS} characters")
|
| 188 |
+
if "\x00" in artifact:
|
| 189 |
+
raise ContractError("artifact contains a NUL byte")
|
| 190 |
+
if not artifact.strip():
|
| 191 |
+
artifact = None
|
| 192 |
+
else:
|
| 193 |
+
raise ContractError("artifact must be a string or null")
|
| 194 |
+
artifact_format = _text(obj.get("artifact_format"), "artifact_format", 32)
|
| 195 |
+
if artifact_format not in ARTIFACT_FORMATS:
|
| 196 |
+
raise ContractError(f"artifact_format must be one of {ARTIFACT_FORMATS}")
|
| 197 |
+
if artifact is None and artifact_format != "TEXT":
|
| 198 |
+
raise ContractError("artifact_format must be TEXT when artifact is null")
|
| 199 |
+
brain_refs = _parse_brain_refs(obj.get("brain_node_ids"))
|
| 200 |
+
source_crosscheck = None
|
| 201 |
+
if source_kind == "CONJECTURE_FACTORY_CACHE":
|
| 202 |
+
source_crosscheck = _factory_crosscheck(conjecture_id, title, statement)
|
| 203 |
+
return {
|
| 204 |
+
"schema_version": ATTEMPT_SCHEMA,
|
| 205 |
+
"source_kind": source_kind,
|
| 206 |
+
"conjecture_id": conjecture_id,
|
| 207 |
+
"title": title,
|
| 208 |
+
"statement": statement,
|
| 209 |
+
"statement_sha256": _sha256(statement),
|
| 210 |
+
"artifact": artifact,
|
| 211 |
+
"artifact_sha256": _sha256(artifact) if artifact is not None else None,
|
| 212 |
+
"artifact_format": artifact_format,
|
| 213 |
+
"brain_node_ids": brain_refs,
|
| 214 |
+
"brain_refs_evidence": "DECLARED_REFERENCES_ONLY",
|
| 215 |
+
"source_crosscheck": source_crosscheck,
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
def _read_events() -> list[dict[str, Any]]:
|
| 220 |
+
if not _STATE_PATH.exists():
|
| 221 |
+
return []
|
| 222 |
+
try:
|
| 223 |
+
if _STATE_PATH.stat().st_size > MAX_LEDGER_BYTES:
|
| 224 |
+
raise LabUnavailable("formal lab ledger exceeds its bounded size")
|
| 225 |
+
lines = _STATE_PATH.read_text(encoding="utf-8").splitlines()
|
| 226 |
+
except LabUnavailable:
|
| 227 |
+
raise
|
| 228 |
+
except OSError as exc:
|
| 229 |
+
raise LabUnavailable(f"formal lab ledger unreadable ({type(exc).__name__})") from exc
|
| 230 |
+
if len(lines) > MAX_EVENTS:
|
| 231 |
+
raise LabUnavailable("formal lab ledger exceeds its bounded event count")
|
| 232 |
+
events: list[dict[str, Any]] = []
|
| 233 |
+
try:
|
| 234 |
+
for line in lines:
|
| 235 |
+
if line.strip():
|
| 236 |
+
value = json.loads(line)
|
| 237 |
+
if not isinstance(value, dict):
|
| 238 |
+
raise ValueError("ledger event is not an object")
|
| 239 |
+
events.append(value)
|
| 240 |
+
except (json.JSONDecodeError, ValueError) as exc:
|
| 241 |
+
raise LabUnavailable("formal lab ledger is structurally invalid") from exc
|
| 242 |
+
verdict = verify_event_chain(events)
|
| 243 |
+
if not verdict["valid"]:
|
| 244 |
+
raise LabUnavailable(f"formal lab ledger chain invalid at event {verdict['broken_at']}")
|
| 245 |
+
return events
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
def verify_event_chain(events: list[dict[str, Any]]) -> dict[str, Any]:
|
| 249 |
+
prev = GENESIS
|
| 250 |
+
for index, event in enumerate(events):
|
| 251 |
+
try:
|
| 252 |
+
payload = event["payload"]
|
| 253 |
+
receipt = event["receipt"]["khipu"]
|
| 254 |
+
dsse = event["receipt"]["dsse"]
|
| 255 |
+
body = {key: receipt[key] for key in (
|
| 256 |
+
"organ", "ns", "seq", "action", "payload_digest", "ts", "prev"
|
| 257 |
+
)}
|
| 258 |
+
receipt_core = {**body, "digest": receipt["digest"],
|
| 259 |
+
"signature": receipt["signature"],
|
| 260 |
+
"chain_verified": receipt["chain_verified"]}
|
| 261 |
+
dsse_payload = base64.b64decode(dsse["payload"], validate=True)
|
| 262 |
+
ok = (
|
| 263 |
+
receipt["seq"] == index
|
| 264 |
+
and receipt["prev"] == prev
|
| 265 |
+
and receipt["payload_digest"] == _sha3(payload)
|
| 266 |
+
and receipt["digest"] == _sha3(body)
|
| 267 |
+
and receipt["signature"] == "UNSIGNED"
|
| 268 |
+
and receipt["chain_verified"] is True
|
| 269 |
+
and dsse["payloadType"] == LOCAL_PAYLOAD_TYPE
|
| 270 |
+
and dsse["signatures"] == []
|
| 271 |
+
and dsse.get("signed") is False
|
| 272 |
+
and dsse_payload == _canonical_bytes(receipt_core)
|
| 273 |
+
)
|
| 274 |
+
except (KeyError, TypeError, ValueError, binascii.Error):
|
| 275 |
+
ok = False
|
| 276 |
+
if not ok:
|
| 277 |
+
return {"valid": False, "depth": len(events), "broken_at": index}
|
| 278 |
+
prev = receipt["digest"]
|
| 279 |
+
return {"valid": True, "depth": len(events), "broken_at": None, "head": prev}
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def _unsigned_dsse(receipt: dict[str, Any]) -> dict[str, Any]:
|
| 283 |
+
return {
|
| 284 |
+
"payloadType": LOCAL_PAYLOAD_TYPE,
|
| 285 |
+
"payload": base64.b64encode(_canonical_bytes(receipt)).decode("ascii"),
|
| 286 |
+
"signatures": [],
|
| 287 |
+
"signed": False,
|
| 288 |
+
"honesty": "UNSIGNED - this local write receipt is hash-chained; no secret or signature fabricated.",
|
| 289 |
+
}
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
def _append_event(ns: str, action: str, payload: dict[str, Any]) -> dict[str, Any]:
|
| 293 |
+
with _WRITE_LOCK:
|
| 294 |
+
events = _read_events()
|
| 295 |
+
if len(events) >= MAX_EVENTS:
|
| 296 |
+
raise LabUnavailable("formal lab event bound reached; archival is required")
|
| 297 |
+
prev = events[-1]["receipt"]["khipu"]["digest"] if events else GENESIS
|
| 298 |
+
body = {
|
| 299 |
+
"organ": "formal-conjecture-lab",
|
| 300 |
+
"ns": ns,
|
| 301 |
+
"seq": len(events),
|
| 302 |
+
"action": action,
|
| 303 |
+
"payload_digest": _sha3(payload),
|
| 304 |
+
"ts": datetime.datetime.now(datetime.timezone.utc).timestamp(),
|
| 305 |
+
"prev": prev,
|
| 306 |
+
}
|
| 307 |
+
receipt = {
|
| 308 |
+
**body,
|
| 309 |
+
"digest": _sha3(body),
|
| 310 |
+
"signature": "UNSIGNED",
|
| 311 |
+
"chain_verified": True,
|
| 312 |
+
}
|
| 313 |
+
event = {"payload": payload, "receipt": {"khipu": receipt, "dsse": _unsigned_dsse(receipt)}}
|
| 314 |
+
encoded = "\n".join(
|
| 315 |
+
json.dumps(row, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
| 316 |
+
for row in [*events, event]
|
| 317 |
+
) + "\n"
|
| 318 |
+
if len(encoded.encode("utf-8")) > MAX_LEDGER_BYTES:
|
| 319 |
+
raise LabUnavailable("formal lab ledger byte bound reached; archival is required")
|
| 320 |
+
try:
|
| 321 |
+
_STATE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
| 322 |
+
tmp = _STATE_PATH.with_suffix(_STATE_PATH.suffix + ".tmp")
|
| 323 |
+
with tmp.open("w", encoding="utf-8", newline="\n") as handle:
|
| 324 |
+
handle.write(encoded)
|
| 325 |
+
handle.flush()
|
| 326 |
+
os.fsync(handle.fileno())
|
| 327 |
+
os.replace(tmp, _STATE_PATH)
|
| 328 |
+
except OSError as exc:
|
| 329 |
+
raise LabUnavailable(f"formal lab ledger write failed ({type(exc).__name__})") from exc
|
| 330 |
+
return event
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
def _fold_attempts(events: list[dict[str, Any]]) -> dict[str, dict[str, Any]]:
|
| 334 |
+
attempts: dict[str, dict[str, Any]] = {}
|
| 335 |
+
for event in events:
|
| 336 |
+
payload = event["payload"]
|
| 337 |
+
if event["receipt"]["khipu"]["action"] == "formal.attempt.declare":
|
| 338 |
+
attempt = dict(payload["attempt"])
|
| 339 |
+
attempt["write_receipt"] = event["receipt"]
|
| 340 |
+
attempts[attempt["attempt_id"]] = attempt
|
| 341 |
+
elif event["receipt"]["khipu"]["action"] == "formal.kernel-receipt.ingest":
|
| 342 |
+
attempt_id = payload["attempt_id"]
|
| 343 |
+
if attempt_id in attempts:
|
| 344 |
+
attempts[attempt_id]["state"] = payload["derived_state"]
|
| 345 |
+
attempts[attempt_id]["kernel_result"] = payload["kernel_result"]
|
| 346 |
+
attempts[attempt_id]["kernel_receipt_verification"] = payload["verification"]
|
| 347 |
+
attempts[attempt_id]["write_receipt"] = event["receipt"]
|
| 348 |
+
return attempts
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
def list_attempts(limit: int = 100) -> dict[str, Any]:
|
| 352 |
+
if not isinstance(limit, int) or not 1 <= limit <= 200:
|
| 353 |
+
raise ContractError("limit must be an integer from 1 through 200")
|
| 354 |
+
events = _read_events()
|
| 355 |
+
attempts = list(_fold_attempts(events).values())
|
| 356 |
+
attempts.sort(key=lambda row: (row.get("declared_at", ""), row["attempt_id"]), reverse=True)
|
| 357 |
+
chain = verify_event_chain(events)
|
| 358 |
+
return {
|
| 359 |
+
"service": "formal-conjecture-lab",
|
| 360 |
+
"attempts": attempts[:limit],
|
| 361 |
+
"count": len(attempts),
|
| 362 |
+
"ledger": chain,
|
| 363 |
+
"read_receipt_minted": False,
|
| 364 |
+
"proof_promotion": "DISABLED",
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
def get_attempt(attempt_id: str) -> dict[str, Any] | None:
|
| 369 |
+
if not isinstance(attempt_id, str) or not _ID_RE.fullmatch(attempt_id):
|
| 370 |
+
raise ContractError("attempt_id is malformed")
|
| 371 |
+
return _fold_attempts(_read_events()).get(attempt_id)
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
def declare_attempt(request: Mapping[str, Any], ns: str = "a11oy") -> dict[str, Any]:
|
| 375 |
+
normalized = normalize_attempt_request(request)
|
| 376 |
+
identity = {
|
| 377 |
+
"conjecture_id": normalized["conjecture_id"],
|
| 378 |
+
"statement_sha256": normalized["statement_sha256"],
|
| 379 |
+
"artifact_sha256": normalized["artifact_sha256"],
|
| 380 |
+
}
|
| 381 |
+
attempt_id = "fcl-" + _sha256(identity)[:24]
|
| 382 |
+
with _WRITE_LOCK:
|
| 383 |
+
prior = get_attempt(attempt_id)
|
| 384 |
+
if prior is not None:
|
| 385 |
+
return {"created": False, "attempt": prior, "write_receipt_minted": False}
|
| 386 |
+
state = KERNEL_UNCHECKED if normalized["artifact"] is not None else DECLARED
|
| 387 |
+
attempt = {
|
| 388 |
+
**normalized,
|
| 389 |
+
"attempt_id": attempt_id,
|
| 390 |
+
"state": state,
|
| 391 |
+
"declared_at": _now(),
|
| 392 |
+
"kernel_result": None,
|
| 393 |
+
"kernel_receipt_verification": None,
|
| 394 |
+
"automatic_proof_promotion": False,
|
| 395 |
+
"proof_status": "NOT_PROMOTED",
|
| 396 |
+
"publication_claim_authorized": False,
|
| 397 |
+
"locked_proven_count": len(LOCKED_SET),
|
| 398 |
+
"locked_set": list(LOCKED_SET),
|
| 399 |
+
"lambda_uniqueness": "Conjecture 1",
|
| 400 |
+
"khipu_bft_safety": "Conjecture 2",
|
| 401 |
+
}
|
| 402 |
+
event = _append_event(ns, "formal.attempt.declare", {"attempt": attempt})
|
| 403 |
+
stored = dict(attempt)
|
| 404 |
+
stored["write_receipt"] = event["receipt"]
|
| 405 |
+
return {"created": True, "attempt": stored, "write_receipt_minted": True}
|
| 406 |
+
|
| 407 |
+
|
| 408 |
+
def _kernel_verifier_status() -> dict[str, Any]:
|
| 409 |
+
try:
|
| 410 |
+
import cryptography # noqa: F401
|
| 411 |
+
import szl_dsse
|
| 412 |
+
|
| 413 |
+
fingerprint = szl_dsse.public_key_fingerprint()
|
| 414 |
+
return {
|
| 415 |
+
"available": True,
|
| 416 |
+
"state": KERNEL_UNCHECKED,
|
| 417 |
+
"trust_anchor": "SZL_COSIGN_PUBLIC_KEY_EMBEDDED",
|
| 418 |
+
"public_key_fingerprint_sha256": fingerprint,
|
| 419 |
+
}
|
| 420 |
+
except Exception as exc:
|
| 421 |
+
return {
|
| 422 |
+
"available": False,
|
| 423 |
+
"state": UNAVAILABLE,
|
| 424 |
+
"reason": f"public-key receipt verifier unavailable ({type(exc).__name__})",
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
|
| 428 |
+
def _decode_verified_kernel_receipt(envelope: Mapping[str, Any], attempt: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
|
| 429 |
+
verifier = _kernel_verifier_status()
|
| 430 |
+
if not verifier["available"]:
|
| 431 |
+
raise LabUnavailable(verifier["reason"])
|
| 432 |
+
env = _mapping(envelope, "dsse_envelope")
|
| 433 |
+
allowed = {
|
| 434 |
+
"payloadType", "payload", "signatures", "_dsse", "_pae_sha256", "_signed_at",
|
| 435 |
+
"honesty", "signed", "verify_key_url",
|
| 436 |
+
}
|
| 437 |
+
required = {"payloadType", "payload", "signatures"}
|
| 438 |
+
if not required <= set(env) or not set(env) <= allowed:
|
| 439 |
+
raise ContractError("dsse_envelope fields are incomplete or unsupported")
|
| 440 |
+
if env.get("payloadType") != KERNEL_PAYLOAD_TYPE:
|
| 441 |
+
raise ContractError(f"payloadType must be {KERNEL_PAYLOAD_TYPE}")
|
| 442 |
+
signatures = env.get("signatures")
|
| 443 |
+
if not isinstance(signatures, list) or len(signatures) != 1:
|
| 444 |
+
raise ContractError("one SZL cosign signature is required")
|
| 445 |
+
signature = _mapping(signatures[0], "signature")
|
| 446 |
+
_strict_keys(signature, {"sig", "keyid"}, "signature")
|
| 447 |
+
if signature.get("keyid") != "szlholdings-cosign":
|
| 448 |
+
raise ContractError("signature keyid is not the configured SZL cosign key")
|
| 449 |
+
try:
|
| 450 |
+
raw = base64.b64decode(str(env.get("payload")), validate=True)
|
| 451 |
+
except (ValueError, binascii.Error) as exc:
|
| 452 |
+
raise ContractError("payload is not strict base64") from exc
|
| 453 |
+
if len(raw) > MAX_BODY_BYTES:
|
| 454 |
+
raise ContractError("kernel receipt payload exceeds the bounded body size")
|
| 455 |
+
try:
|
| 456 |
+
payload = json.loads(raw.decode("utf-8"))
|
| 457 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 458 |
+
raise ContractError("kernel receipt payload is not one UTF-8 JSON object") from exc
|
| 459 |
+
payload = dict(_mapping(payload, "kernel receipt payload"))
|
| 460 |
+
fields = {
|
| 461 |
+
"schema_version", "attempt_id", "conjecture_id", "statement_sha256",
|
| 462 |
+
"artifact_sha256", "checker_id", "checker_version", "kernel_commit_sha256",
|
| 463 |
+
"exit_code", "sorry_count", "unsafe_declaration_count", "compiler_output_sha256",
|
| 464 |
+
"checked_at", "claimed_verdict",
|
| 465 |
+
}
|
| 466 |
+
_strict_keys(payload, fields, "kernel receipt payload")
|
| 467 |
+
if payload.get("schema_version") != KERNEL_SCHEMA:
|
| 468 |
+
raise ContractError(f"kernel schema_version must be {KERNEL_SCHEMA}")
|
| 469 |
+
if payload.get("attempt_id") != attempt["attempt_id"]:
|
| 470 |
+
raise ContractError("kernel receipt attempt_id does not match the stored attempt")
|
| 471 |
+
if payload.get("conjecture_id") != attempt["conjecture_id"]:
|
| 472 |
+
raise ContractError("kernel receipt conjecture_id does not match the stored attempt")
|
| 473 |
+
if payload.get("statement_sha256") != attempt["statement_sha256"]:
|
| 474 |
+
raise ContractError("kernel receipt statement hash does not match the stored statement")
|
| 475 |
+
if payload.get("artifact_sha256") != attempt["artifact_sha256"]:
|
| 476 |
+
raise ContractError("kernel receipt artifact hash does not match the stored artifact")
|
| 477 |
+
if payload.get("checker_id") != "LEAN4":
|
| 478 |
+
raise ContractError("checker_id must be LEAN4")
|
| 479 |
+
_text(payload.get("checker_version"), "checker_version", 128)
|
| 480 |
+
_hex64(payload.get("kernel_commit_sha256"), "kernel_commit_sha256")
|
| 481 |
+
_hex64(payload.get("compiler_output_sha256"), "compiler_output_sha256")
|
| 482 |
+
for name in ("exit_code", "sorry_count", "unsafe_declaration_count"):
|
| 483 |
+
value = payload.get(name)
|
| 484 |
+
if not isinstance(value, int) or isinstance(value, bool) or value < 0 or value > 1_000_000:
|
| 485 |
+
raise ContractError(f"{name} must be a bounded non-negative integer")
|
| 486 |
+
_text(payload.get("checked_at"), "checked_at", 96)
|
| 487 |
+
claimed = _text(payload.get("claimed_verdict"), "claimed_verdict", 32)
|
| 488 |
+
if claimed not in ("ACCEPTED", "REJECTED"):
|
| 489 |
+
raise ContractError("claimed_verdict must be ACCEPTED or REJECTED")
|
| 490 |
+
import szl_dsse
|
| 491 |
+
|
| 492 |
+
verification = szl_dsse.verify_envelope(dict(env))
|
| 493 |
+
if verification.get("verified") is not True:
|
| 494 |
+
raise ContractError(
|
| 495 |
+
"kernel DSSE signature did not verify: " + str(verification.get("reason") or "unknown")[:160]
|
| 496 |
+
)
|
| 497 |
+
if verification.get("keyid_expected") != "szlholdings-cosign":
|
| 498 |
+
raise ContractError("kernel receipt verification used an unexpected trust anchor")
|
| 499 |
+
return payload, verification
|
| 500 |
+
|
| 501 |
+
|
| 502 |
+
def ingest_kernel_receipt(attempt_id: str, request: Mapping[str, Any], ns: str = "a11oy") -> dict[str, Any]:
|
| 503 |
+
obj = _mapping(request, "kernel receipt request")
|
| 504 |
+
_strict_keys(obj, {"schema_version", "dsse_envelope"}, "kernel receipt request")
|
| 505 |
+
if obj.get("schema_version") != KERNEL_SCHEMA:
|
| 506 |
+
raise ContractError(f"schema_version must be {KERNEL_SCHEMA}")
|
| 507 |
+
with _WRITE_LOCK:
|
| 508 |
+
attempt = get_attempt(attempt_id)
|
| 509 |
+
if attempt is None:
|
| 510 |
+
raise StateConflict("attempt does not exist")
|
| 511 |
+
if attempt.get("artifact_sha256") is None:
|
| 512 |
+
raise StateConflict("attempt has no formal artifact to check")
|
| 513 |
+
payload, verification = _decode_verified_kernel_receipt(obj.get("dsse_envelope"), attempt)
|
| 514 |
+
derived = (
|
| 515 |
+
KERNEL_ACCEPTED
|
| 516 |
+
if payload["exit_code"] == 0
|
| 517 |
+
and payload["sorry_count"] == 0
|
| 518 |
+
and payload["unsafe_declaration_count"] == 0
|
| 519 |
+
else KERNEL_REJECTED
|
| 520 |
+
)
|
| 521 |
+
envelope_digest = _sha256(dict(_mapping(obj.get("dsse_envelope"), "dsse_envelope")))
|
| 522 |
+
prior_result = attempt.get("kernel_result")
|
| 523 |
+
if attempt["state"] in (KERNEL_ACCEPTED, KERNEL_REJECTED):
|
| 524 |
+
if prior_result and prior_result.get("envelope_sha256") == envelope_digest:
|
| 525 |
+
return {"updated": False, "attempt": attempt, "write_receipt_minted": False}
|
| 526 |
+
raise StateConflict("attempt already has a different terminal kernel receipt")
|
| 527 |
+
if attempt["state"] != KERNEL_UNCHECKED:
|
| 528 |
+
raise StateConflict("attempt is not ready for a kernel receipt")
|
| 529 |
+
kernel_result = {
|
| 530 |
+
"derived_state": derived,
|
| 531 |
+
"derived_from": "SIGNED_EXIT_CODE_AND_SIGNED_SORRY_UNSAFE_COUNTS",
|
| 532 |
+
"client_claimed_verdict": payload["claimed_verdict"],
|
| 533 |
+
"client_label_trusted": False,
|
| 534 |
+
"label_conflict": payload["claimed_verdict"] != (
|
| 535 |
+
"ACCEPTED" if derived == KERNEL_ACCEPTED else "REJECTED"
|
| 536 |
+
),
|
| 537 |
+
"checker_id": payload["checker_id"],
|
| 538 |
+
"checker_version": payload["checker_version"],
|
| 539 |
+
"kernel_commit_sha256": payload["kernel_commit_sha256"],
|
| 540 |
+
"exit_code": payload["exit_code"],
|
| 541 |
+
"sorry_count": payload["sorry_count"],
|
| 542 |
+
"unsafe_declaration_count": payload["unsafe_declaration_count"],
|
| 543 |
+
"compiler_output_sha256": payload["compiler_output_sha256"],
|
| 544 |
+
"checked_at": payload["checked_at"],
|
| 545 |
+
"envelope_sha256": envelope_digest,
|
| 546 |
+
"proof_promoted": False,
|
| 547 |
+
"publication_claim_authorized": False,
|
| 548 |
+
"note": "Kernel acceptance is recorded evidence only; it is not automatic proof promotion.",
|
| 549 |
+
}
|
| 550 |
+
event_payload = {
|
| 551 |
+
"attempt_id": attempt_id,
|
| 552 |
+
"derived_state": derived,
|
| 553 |
+
"kernel_result": kernel_result,
|
| 554 |
+
"verification": {
|
| 555 |
+
"verified": True,
|
| 556 |
+
"keyid_expected": verification.get("keyid_expected"),
|
| 557 |
+
"pub_fingerprint_sha256": verification.get("pub_fingerprint_sha256"),
|
| 558 |
+
"pae_sha256": verification.get("pae_sha256"),
|
| 559 |
+
},
|
| 560 |
+
}
|
| 561 |
+
event = _append_event(ns, "formal.kernel-receipt.ingest", event_payload)
|
| 562 |
+
updated = get_attempt(attempt_id)
|
| 563 |
+
if updated is None:
|
| 564 |
+
raise LabUnavailable("attempt disappeared after a successful ledger write")
|
| 565 |
+
updated["write_receipt"] = event["receipt"]
|
| 566 |
+
return {"updated": True, "attempt": updated, "write_receipt_minted": True}
|
| 567 |
+
|
| 568 |
+
|
| 569 |
+
def status() -> dict[str, Any]:
|
| 570 |
+
verifier = _kernel_verifier_status()
|
| 571 |
+
try:
|
| 572 |
+
bundle = list_attempts(limit=200)
|
| 573 |
+
attempts = bundle["attempts"]
|
| 574 |
+
ledger = bundle["ledger"]
|
| 575 |
+
storage_state = "READY"
|
| 576 |
+
reason = None
|
| 577 |
+
except LabUnavailable as exc:
|
| 578 |
+
attempts = []
|
| 579 |
+
ledger = {"valid": False, "depth": 0, "broken_at": None}
|
| 580 |
+
storage_state = UNAVAILABLE
|
| 581 |
+
reason = str(exc)
|
| 582 |
+
counts = {state: 0 for state in STATES}
|
| 583 |
+
for attempt in attempts:
|
| 584 |
+
counts[attempt["state"]] = counts.get(attempt["state"], 0) + 1
|
| 585 |
+
return {
|
| 586 |
+
"service": "formal-conjecture-lab",
|
| 587 |
+
"ready": storage_state == "READY",
|
| 588 |
+
"storage_state": storage_state,
|
| 589 |
+
"reason": reason,
|
| 590 |
+
"states": list(STATES),
|
| 591 |
+
"attempt_state_counts": counts,
|
| 592 |
+
"ledger": ledger,
|
| 593 |
+
"kernel_execution": {
|
| 594 |
+
"state": UNAVAILABLE,
|
| 595 |
+
"reason": "no in-process prover execution path; arbitrary commands and network are disabled",
|
| 596 |
+
},
|
| 597 |
+
"kernel_receipt_verification": verifier,
|
| 598 |
+
"kernel_receipt_contract": {
|
| 599 |
+
"schema_version": KERNEL_SCHEMA,
|
| 600 |
+
"payload_type": KERNEL_PAYLOAD_TYPE,
|
| 601 |
+
"checker_id": "LEAN4",
|
| 602 |
+
"signature_keyid": "szlholdings-cosign",
|
| 603 |
+
"exact_bindings": [
|
| 604 |
+
"attempt_id", "conjecture_id", "statement_sha256", "artifact_sha256"
|
| 605 |
+
],
|
| 606 |
+
"derived_acceptance": (
|
| 607 |
+
"verified DSSE AND exit_code == 0 AND sorry_count == 0 AND "
|
| 608 |
+
"unsafe_declaration_count == 0"
|
| 609 |
+
),
|
| 610 |
+
"client_claimed_verdict_controls_state": False,
|
| 611 |
+
},
|
| 612 |
+
"endpoints": {
|
| 613 |
+
"status": "GET /api/a11oy/v1/formal-conjecture-lab/status",
|
| 614 |
+
"list": "GET /api/a11oy/v1/formal-conjecture-lab/attempts?limit=100",
|
| 615 |
+
"get": "GET /api/a11oy/v1/formal-conjecture-lab/attempts/{attempt_id}",
|
| 616 |
+
"declare": "POST /api/a11oy/v1/formal-conjecture-lab/attempts",
|
| 617 |
+
"ingest_kernel_receipt": (
|
| 618 |
+
"POST /api/a11oy/v1/formal-conjecture-lab/attempts/{attempt_id}/kernel-receipts"
|
| 619 |
+
),
|
| 620 |
+
},
|
| 621 |
+
"controls": {
|
| 622 |
+
"network_calls": "DISABLED",
|
| 623 |
+
"command_execution": "DISABLED",
|
| 624 |
+
"arbitrary_code": "DISABLED",
|
| 625 |
+
"secret_reads": "DISABLED",
|
| 626 |
+
"strict_contracts": True,
|
| 627 |
+
"body_limit_bytes": MAX_BODY_BYTES,
|
| 628 |
+
"max_events": MAX_EVENTS,
|
| 629 |
+
"max_ledger_bytes": MAX_LEDGER_BYTES,
|
| 630 |
+
},
|
| 631 |
+
"proof_policy": {
|
| 632 |
+
"automatic_promotion": False,
|
| 633 |
+
"kernel_accepted_means_proved": False,
|
| 634 |
+
"publication_claim_authorized": False,
|
| 635 |
+
"locked_proven_count": len(LOCKED_SET),
|
| 636 |
+
"locked_set": list(LOCKED_SET),
|
| 637 |
+
"lambda_uniqueness": "Conjecture 1",
|
| 638 |
+
"khipu_bft_safety": "Conjecture 2",
|
| 639 |
+
},
|
| 640 |
+
"receipt_policy": "RECEIPT-ON-WRITE-NOT-ON-READ",
|
| 641 |
+
}
|
| 642 |
+
|
| 643 |
+
|
| 644 |
+
async def _read_body(request: Any) -> dict[str, Any]:
|
| 645 |
+
content_length = request.headers.get("content-length")
|
| 646 |
+
if content_length is not None:
|
| 647 |
+
try:
|
| 648 |
+
declared = int(content_length)
|
| 649 |
+
except ValueError as exc:
|
| 650 |
+
raise ContractError("content-length must be a non-negative integer") from exc
|
| 651 |
+
if declared < 0:
|
| 652 |
+
raise ContractError("content-length must be a non-negative integer")
|
| 653 |
+
if declared > MAX_BODY_BYTES:
|
| 654 |
+
raise ContractError(f"request body exceeds {MAX_BODY_BYTES} bytes")
|
| 655 |
+
data = bytearray()
|
| 656 |
+
async for chunk in request.stream():
|
| 657 |
+
if len(data) + len(chunk) > MAX_BODY_BYTES:
|
| 658 |
+
raise ContractError(f"request body exceeds {MAX_BODY_BYTES} bytes")
|
| 659 |
+
data.extend(chunk)
|
| 660 |
+
try:
|
| 661 |
+
value = json.loads(bytes(data).decode("utf-8"))
|
| 662 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 663 |
+
raise ContractError("request body must be one UTF-8 JSON object") from exc
|
| 664 |
+
return dict(_mapping(value, "request body"))
|
| 665 |
+
|
| 666 |
+
|
| 667 |
+
def register(app: Any, ns: str = "a11oy") -> dict[str, Any]:
|
| 668 |
+
"""Register bounded read/write routes before both application catch-alls."""
|
| 669 |
+
from fastapi import Request
|
| 670 |
+
from fastapi.responses import JSONResponse
|
| 671 |
+
|
| 672 |
+
base = f"/api/{ns}/v1/formal-conjecture-lab"
|
| 673 |
+
|
| 674 |
+
@app.get(base + "/status")
|
| 675 |
+
async def _formal_lab_status() -> JSONResponse:
|
| 676 |
+
return JSONResponse(status())
|
| 677 |
+
|
| 678 |
+
@app.get(base + "/attempts")
|
| 679 |
+
async def _formal_lab_attempts(limit: int = 100) -> JSONResponse:
|
| 680 |
+
try:
|
| 681 |
+
return JSONResponse(list_attempts(limit))
|
| 682 |
+
except ContractError as exc:
|
| 683 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=422)
|
| 684 |
+
except LabUnavailable as exc:
|
| 685 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=503)
|
| 686 |
+
|
| 687 |
+
@app.get(base + "/attempts/{attempt_id}")
|
| 688 |
+
async def _formal_lab_attempt(attempt_id: str) -> JSONResponse:
|
| 689 |
+
try:
|
| 690 |
+
attempt = get_attempt(attempt_id)
|
| 691 |
+
except ContractError as exc:
|
| 692 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=422)
|
| 693 |
+
except LabUnavailable as exc:
|
| 694 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=503)
|
| 695 |
+
if attempt is None:
|
| 696 |
+
return JSONResponse({"state": UNAVAILABLE, "error": "attempt not found"}, status_code=404)
|
| 697 |
+
return JSONResponse({"attempt": attempt, "read_receipt_minted": False})
|
| 698 |
+
|
| 699 |
+
@app.post(base + "/attempts")
|
| 700 |
+
async def _formal_lab_declare(request: Request) -> JSONResponse:
|
| 701 |
+
try:
|
| 702 |
+
result = declare_attempt(await _read_body(request), ns)
|
| 703 |
+
return JSONResponse(result, status_code=201 if result["created"] else 200)
|
| 704 |
+
except ContractError as exc:
|
| 705 |
+
code = 413 if "body exceeds" in str(exc) else 422
|
| 706 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=code)
|
| 707 |
+
except LabUnavailable as exc:
|
| 708 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=503)
|
| 709 |
+
|
| 710 |
+
@app.post(base + "/attempts/{attempt_id}/kernel-receipts")
|
| 711 |
+
async def _formal_lab_kernel_receipt(attempt_id: str, request: Request) -> JSONResponse:
|
| 712 |
+
try:
|
| 713 |
+
return JSONResponse(ingest_kernel_receipt(attempt_id, await _read_body(request), ns))
|
| 714 |
+
except ContractError as exc:
|
| 715 |
+
code = 413 if "body exceeds" in str(exc) else 422
|
| 716 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=code)
|
| 717 |
+
except StateConflict as exc:
|
| 718 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=409)
|
| 719 |
+
except LabUnavailable as exc:
|
| 720 |
+
return JSONResponse({"state": UNAVAILABLE, "error": str(exc)}, status_code=503)
|
| 721 |
+
|
| 722 |
+
return {
|
| 723 |
+
"registered": True,
|
| 724 |
+
"base": base,
|
| 725 |
+
"kernel_execution": UNAVAILABLE,
|
| 726 |
+
"proof_promotion": "DISABLED",
|
| 727 |
+
}
|
|
@@ -65,6 +65,8 @@ LABEL_MEASURED = "MEASURED"
|
|
| 65 |
LABEL_BOUNDED = "MEASURED_SHARED_BOUNDED"
|
| 66 |
LABEL_MODELED = "MODELED"
|
| 67 |
LABEL_UNAVAILABLE = "UNAVAILABLE"
|
|
|
|
|
|
|
| 68 |
|
| 69 |
# Grounding subgraph size (k) for the PPR retrieval.
|
| 70 |
GROUND_K = 12
|
|
@@ -286,7 +288,8 @@ def _prev_hash():
|
|
| 286 |
|
| 287 |
|
| 288 |
def _make_receipt(query, subgraph_ids, answer_digest, energy, tokens, model,
|
| 289 |
-
prev_hash
|
|
|
|
| 290 |
"""Build a DSSE-style SHA-256 hash-chained receipt over the governed turn.
|
| 291 |
|
| 292 |
tokens_per_joule is populated ONLY when BOTH a real output-token count and a
|
|
@@ -302,14 +305,22 @@ def _make_receipt(query, subgraph_ids, answer_digest, energy, tokens, model,
|
|
| 302 |
# tokens_per_joule inherits the joule measurement's honest label.
|
| 303 |
tpj_label = energy_label
|
| 304 |
body = {
|
| 305 |
-
"schema":
|
| 306 |
"chain_alg": "sha256",
|
|
|
|
| 307 |
"q": query,
|
| 308 |
"query_digest": _sha(query),
|
| 309 |
"subgraph_ids": list(subgraph_ids),
|
| 310 |
"subgraph_size": len(subgraph_ids),
|
| 311 |
"answer_digest": answer_digest,
|
| 312 |
"model": model,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 313 |
"joules": joules,
|
| 314 |
"energy_label": energy_label,
|
| 315 |
"tokens": int(tokens or 0),
|
|
@@ -325,7 +336,7 @@ def _make_receipt(query, subgraph_ids, answer_digest, energy, tokens, model,
|
|
| 325 |
|
| 326 |
def _receipt_hash(body):
|
| 327 |
"""Canonical SHA-256 over the load-bearing receipt fields (chain link)."""
|
| 328 |
-
|
| 329 |
body.get("prev_hash", ""),
|
| 330 |
body.get("query_digest", ""),
|
| 331 |
body.get("answer_digest", ""),
|
|
@@ -335,7 +346,84 @@ def _receipt_hash(body):
|
|
| 335 |
str(body.get("model")),
|
| 336 |
body.get("node", ""),
|
| 337 |
body.get("ts", ""),
|
| 338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 339 |
|
| 340 |
|
| 341 |
def _append(receipt):
|
|
@@ -406,7 +494,12 @@ def govern_infer(query, ns="a11oy"):
|
|
| 406 |
prev = _prev_hash()
|
| 407 |
receipt = _make_receipt(query, subgraph_ids, answer_digest, energy,
|
| 408 |
answer.get("tokens", 0), answer.get("model"),
|
| 409 |
-
prev
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 410 |
_append(receipt)
|
| 411 |
dsse = _maybe_dsse(receipt)
|
| 412 |
|
|
@@ -476,6 +569,9 @@ def list_receipts(limit=50):
|
|
| 476 |
"q": r.get("q"),
|
| 477 |
"subgraph_size": r.get("subgraph_size"),
|
| 478 |
"model": r.get("model"),
|
|
|
|
|
|
|
|
|
|
| 479 |
"joules": r.get("joules"),
|
| 480 |
"energy_label": r.get("energy_label"),
|
| 481 |
"tokens": r.get("tokens"),
|
|
|
|
| 65 |
LABEL_BOUNDED = "MEASURED_SHARED_BOUNDED"
|
| 66 |
LABEL_MODELED = "MODELED"
|
| 67 |
LABEL_UNAVAILABLE = "UNAVAILABLE"
|
| 68 |
+
RECEIPT_SCHEMA_V1 = "szl.govern.brain-infer/v1"
|
| 69 |
+
RECEIPT_SCHEMA_V2 = "szl.govern.inference/v2"
|
| 70 |
|
| 71 |
# Grounding subgraph size (k) for the PPR retrieval.
|
| 72 |
GROUND_K = 12
|
|
|
|
| 288 |
|
| 289 |
|
| 290 |
def _make_receipt(query, subgraph_ids, answer_digest, energy, tokens, model,
|
| 291 |
+
prev_hash, *, answer_available=False,
|
| 292 |
+
receipt_source="brain-infer", base_url=""):
|
| 293 |
"""Build a DSSE-style SHA-256 hash-chained receipt over the governed turn.
|
| 294 |
|
| 295 |
tokens_per_joule is populated ONLY when BOTH a real output-token count and a
|
|
|
|
| 305 |
# tokens_per_joule inherits the joule measurement's honest label.
|
| 306 |
tpj_label = energy_label
|
| 307 |
body = {
|
| 308 |
+
"schema": RECEIPT_SCHEMA_V2,
|
| 309 |
"chain_alg": "sha256",
|
| 310 |
+
"receipt_source": str(receipt_source or "unknown"),
|
| 311 |
"q": query,
|
| 312 |
"query_digest": _sha(query),
|
| 313 |
"subgraph_ids": list(subgraph_ids),
|
| 314 |
"subgraph_size": len(subgraph_ids),
|
| 315 |
"answer_digest": answer_digest,
|
| 316 |
"model": model,
|
| 317 |
+
"answer_available": bool(answer_available),
|
| 318 |
+
# A durable receipt is evidence of successful inference only when the
|
| 319 |
+
# provider returned real non-empty text and named the model that ran.
|
| 320 |
+
# Failed attempts still receive an attempt receipt, but never set this.
|
| 321 |
+
"inference_receipted": bool(answer_available and answer_digest
|
| 322 |
+
and model),
|
| 323 |
+
"base_url_sha256": _sha(base_url) if base_url else None,
|
| 324 |
"joules": joules,
|
| 325 |
"energy_label": energy_label,
|
| 326 |
"tokens": int(tokens or 0),
|
|
|
|
| 336 |
|
| 337 |
def _receipt_hash(body):
|
| 338 |
"""Canonical SHA-256 over the load-bearing receipt fields (chain link)."""
|
| 339 |
+
parts = [
|
| 340 |
body.get("prev_hash", ""),
|
| 341 |
body.get("query_digest", ""),
|
| 342 |
body.get("answer_digest", ""),
|
|
|
|
| 346 |
str(body.get("model")),
|
| 347 |
body.get("node", ""),
|
| 348 |
body.get("ts", ""),
|
| 349 |
+
]
|
| 350 |
+
# Preserve verification of existing v1 receipts while binding every new
|
| 351 |
+
# inference-state field into the v2 hash.
|
| 352 |
+
if body.get("schema") == RECEIPT_SCHEMA_V2:
|
| 353 |
+
parts.extend([
|
| 354 |
+
body.get("receipt_source", ""),
|
| 355 |
+
str(bool(body.get("answer_available"))),
|
| 356 |
+
str(bool(body.get("inference_receipted"))),
|
| 357 |
+
body.get("base_url_sha256") or "",
|
| 358 |
+
])
|
| 359 |
+
return _sha(*parts)
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
def record_provider_generation(query, text, model, *, tokens=0, base_url=""):
|
| 363 |
+
"""Persist one successful provider generation as a durable v2 receipt.
|
| 364 |
+
|
| 365 |
+
This is called only from POST/write paths after a provider returned real,
|
| 366 |
+
non-empty text. Reachability, configuration, and a routing decision are not
|
| 367 |
+
enough. The append is fsync'd and immediately replay-verified; failure is
|
| 368 |
+
returned honestly and never upgraded to receipted inference.
|
| 369 |
+
"""
|
| 370 |
+
query = (query or "").strip()
|
| 371 |
+
text = (text or "").strip()
|
| 372 |
+
model = (model or "").strip()
|
| 373 |
+
if not query or not text or not model:
|
| 374 |
+
return {"ok": False, "inference_receipted": False,
|
| 375 |
+
"reason": "query, non-empty provider text, and model are required"}
|
| 376 |
+
try:
|
| 377 |
+
token_count = max(0, int(tokens or 0))
|
| 378 |
+
except (TypeError, ValueError):
|
| 379 |
+
token_count = 0
|
| 380 |
+
energy = {"joules": None, "label": LABEL_UNAVAILABLE,
|
| 381 |
+
"reason": "provider-route receipt did not bracket an NVML meter delta"}
|
| 382 |
+
with _LOCK:
|
| 383 |
+
prev = _prev_hash()
|
| 384 |
+
receipt = _make_receipt(
|
| 385 |
+
query, [], _sha(text), energy, token_count, model, prev,
|
| 386 |
+
answer_available=True, receipt_source="llm-route", base_url=base_url)
|
| 387 |
+
_append(receipt)
|
| 388 |
+
chain = _read_chain()
|
| 389 |
+
persisted = bool(chain and chain[-1].get("receipt_hash") == receipt["receipt_hash"])
|
| 390 |
+
verified = persisted and _verify_entry(chain[-1], prev)
|
| 391 |
+
return {
|
| 392 |
+
"ok": bool(verified),
|
| 393 |
+
"inference_receipted": bool(verified),
|
| 394 |
+
"receipt_hash": receipt["receipt_hash"] if verified else None,
|
| 395 |
+
"schema": receipt["schema"],
|
| 396 |
+
"reason": ("durable inference receipt appended and replay-verified"
|
| 397 |
+
if verified else "receipt append could not be replay-verified"),
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
|
| 401 |
+
def inference_receipt_status(model=""):
|
| 402 |
+
"""Read-only successful-inference receipt status; never emits a receipt."""
|
| 403 |
+
wanted = (model or "").strip()
|
| 404 |
+
chain = _read_chain()
|
| 405 |
+
prev = ""
|
| 406 |
+
broken = []
|
| 407 |
+
successful = []
|
| 408 |
+
for idx, entry in enumerate(chain):
|
| 409 |
+
valid = _verify_entry(entry, prev)
|
| 410 |
+
if not valid:
|
| 411 |
+
broken.append(idx)
|
| 412 |
+
prev = entry.get("receipt_hash", prev)
|
| 413 |
+
entry_model = str(entry.get("model") or "")
|
| 414 |
+
model_match = (not wanted or entry_model == wanted
|
| 415 |
+
or entry_model.endswith(":" + wanted))
|
| 416 |
+
if valid and entry.get("inference_receipted") is True and model_match:
|
| 417 |
+
successful.append(entry)
|
| 418 |
+
latest = successful[-1] if successful else None
|
| 419 |
+
return {
|
| 420 |
+
"inference_receipted": bool(successful and not broken),
|
| 421 |
+
"successful_receipt_count": len(successful),
|
| 422 |
+
"total_receipt_count": len(chain),
|
| 423 |
+
"chain_ok": not broken,
|
| 424 |
+
"latest_receipt_hash": latest.get("receipt_hash") if latest else None,
|
| 425 |
+
"latest_model": latest.get("model") if latest else None,
|
| 426 |
+
}
|
| 427 |
|
| 428 |
|
| 429 |
def _append(receipt):
|
|
|
|
| 494 |
prev = _prev_hash()
|
| 495 |
receipt = _make_receipt(query, subgraph_ids, answer_digest, energy,
|
| 496 |
answer.get("tokens", 0), answer.get("model"),
|
| 497 |
+
prev,
|
| 498 |
+
answer_available=bool(answer.get("available")
|
| 499 |
+
and ans_text),
|
| 500 |
+
receipt_source="brain-infer",
|
| 501 |
+
base_url=_local_llm_url()
|
| 502 |
+
or _sovereign_gateway())
|
| 503 |
_append(receipt)
|
| 504 |
dsse = _maybe_dsse(receipt)
|
| 505 |
|
|
|
|
| 569 |
"q": r.get("q"),
|
| 570 |
"subgraph_size": r.get("subgraph_size"),
|
| 571 |
"model": r.get("model"),
|
| 572 |
+
"receipt_source": r.get("receipt_source", "brain-infer"),
|
| 573 |
+
"answer_available": bool(r.get("answer_available")),
|
| 574 |
+
"inference_receipted": bool(r.get("inference_receipted")),
|
| 575 |
"joules": r.get("joules"),
|
| 576 |
"energy_label": r.get("energy_label"),
|
| 577 |
"tokens": r.get("tokens"),
|
|
@@ -25,10 +25,11 @@ The VRAM-resident, three-layer quant pipeline validated in GPU_QUANT_RESEARCH.md
|
|
| 25 |
HONESTY SPINE (doctrine v11 — the non-negotiable part of this build):
|
| 26 |
* EVERY output is a SAMPLE_SIGNAL: synthetic / illustrative returns, NOT a live feed,
|
| 27 |
NO_BACKTEST_VALIDATED. We have NOT run a backtest. We do NOT claim live-trading.
|
| 28 |
-
* The compute path here is the HONEST CPU
|
| 29 |
a pure-Python Vietoris-Rips β0/β1 over a thresholded distance graph). The GPU path
|
| 30 |
-
(cuML LedoitWolf + cuPy eigh + giotto-tda / Ripser++) is labeled ROADMAP
|
| 31 |
-
|
|
|
|
| 32 |
* Every receipt is SIGNED via szl_dsse.sign_payload (REAL ECDSA when the cosign key
|
| 33 |
is present in the runtime; an explicit UNSIGNED honesty marker otherwise — never a
|
| 34 |
fabricated signature). The label SAMPLE_SIGNAL | NOT_LIVE | NO_BACKTEST_VALIDATED is
|
|
@@ -105,8 +106,8 @@ def _np_present() -> bool:
|
|
| 105 |
|
| 106 |
def _sovereign_state() -> dict:
|
| 107 |
"""LIVE sovereign-inference posture (delegated to the orchestrator — the authority).
|
| 108 |
-
Honest default not-sovereign on any failure.
|
| 109 |
-
|
| 110 |
try:
|
| 111 |
import a11oy_code_orchestrator as _orch # type: ignore
|
| 112 |
st = _orch._sovereign_inference_state()
|
|
@@ -127,23 +128,33 @@ def _gpu_reachable(state: dict | None = None) -> bool:
|
|
| 127 |
def _compute_backend() -> dict:
|
| 128 |
"""Which compute path actually ran, honestly labeled.
|
| 129 |
|
| 130 |
-
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
"""
|
| 133 |
libs = _gpu_libs_present()
|
| 134 |
reachable = _gpu_reachable()
|
| 135 |
-
|
|
|
|
|
|
|
| 136 |
return {
|
| 137 |
-
"backend": "
|
| 138 |
-
"
|
|
|
|
| 139 |
"gpu_reachable": reachable,
|
| 140 |
"gpu_libs_present": libs,
|
|
|
|
|
|
|
|
|
|
| 141 |
"honest_note": (
|
| 142 |
-
"
|
| 143 |
-
|
| 144 |
-
"
|
| 145 |
-
"
|
| 146 |
-
"
|
| 147 |
}
|
| 148 |
|
| 149 |
|
|
@@ -757,7 +768,8 @@ def tiers_panel() -> dict:
|
|
| 757 |
"config": "vLLM --tensor-parallel-size 2 shards ONE larger model across a-11-oy.com GPU + RTX 4000",
|
| 758 |
"fits": "e.g. Qwen3-32B comfortably, or a quantized Nemotron-3-Super across combined VRAM",
|
| 759 |
"gpus": [per_gpu("a-11-oy.com GPU"), per_gpu("NVIDIA RTX 4000 (Ada, ~20GB)")],
|
| 760 |
-
"label": "
|
|
|
|
| 761 |
},
|
| 762 |
{
|
| 763 |
"tier": "sovereign-local · ROLE-SPLIT (recommended for agent loops)",
|
|
@@ -768,7 +780,8 @@ def tiers_panel() -> dict:
|
|
| 768 |
"fits": "keeps the main GPU from stalling on inline review/draft — best fit for our agent+Auto-Review arch",
|
| 769 |
"gpus": [per_gpu("a-11-oy.com GPU · primary model"),
|
| 770 |
per_gpu("RTX 4000 · classifier+draft+embeddings")],
|
| 771 |
-
"label": "
|
|
|
|
| 772 |
},
|
| 773 |
{
|
| 774 |
"tier": "cloud · NVIDIA NIM (Nemotron 3 Ultra) — frontier/hard tier",
|
|
|
|
| 25 |
HONESTY SPINE (doctrine v11 — the non-negotiable part of this build):
|
| 26 |
* EVERY output is a SAMPLE_SIGNAL: synthetic / illustrative returns, NOT a live feed,
|
| 27 |
NO_BACKTEST_VALIDATED. We have NOT run a backtest. We do NOT claim live-trading.
|
| 28 |
+
* The compute path here is the HONEST CPU REFERENCE (pure-Python linear algebra +
|
| 29 |
a pure-Python Vietoris-Rips β0/β1 over a thresholded distance graph). The GPU path
|
| 30 |
+
(cuML LedoitWolf + cuPy eigh + giotto-tda / Ripser++) is labeled ROADMAP. GPU
|
| 31 |
+
reachability and dependency imports are readiness only; MEASURED requires a distinct
|
| 32 |
+
accelerated path plus device/kernel/timing execution evidence.
|
| 33 |
* Every receipt is SIGNED via szl_dsse.sign_payload (REAL ECDSA when the cosign key
|
| 34 |
is present in the runtime; an explicit UNSIGNED honesty marker otherwise — never a
|
| 35 |
fabricated signature). The label SAMPLE_SIGNAL | NOT_LIVE | NO_BACKTEST_VALIDATED is
|
|
|
|
| 106 |
|
| 107 |
def _sovereign_state() -> dict:
|
| 108 |
"""LIVE sovereign-inference posture (delegated to the orchestrator — the authority).
|
| 109 |
+
Honest default not-sovereign on any failure. This state is reachability evidence,
|
| 110 |
+
never proof that the finance quant pipeline executed on a GPU."""
|
| 111 |
try:
|
| 112 |
import a11oy_code_orchestrator as _orch # type: ignore
|
| 113 |
st = _orch._sovereign_inference_state()
|
|
|
|
| 128 |
def _compute_backend() -> dict:
|
| 129 |
"""Which compute path actually ran, honestly labeled.
|
| 130 |
|
| 131 |
+
The numerical layer implementations in this module are currently the pure-Python
|
| 132 |
+
reference path. Dependency availability is *readiness*, not execution evidence:
|
| 133 |
+
merely finding a sovereign GPU and importing cuML/cuPy must never relabel CPU
|
| 134 |
+
results as GPU-MEASURED. When an accelerated implementation is added it must
|
| 135 |
+
supply execution evidence (device, kernel/implementation id, and timing receipt)
|
| 136 |
+
before this contract can emit a MEASURED GPU label.
|
| 137 |
"""
|
| 138 |
libs = _gpu_libs_present()
|
| 139 |
reachable = _gpu_reachable()
|
| 140 |
+
acceleration_dependencies_ready = bool(
|
| 141 |
+
reachable and libs.get("cuml") and libs.get("cupy")
|
| 142 |
+
)
|
| 143 |
return {
|
| 144 |
+
"backend": "CPU pure-Python reference",
|
| 145 |
+
"compute_path": "CPU_REFERENCE",
|
| 146 |
+
"label": "SAMPLE",
|
| 147 |
"gpu_reachable": reachable,
|
| 148 |
"gpu_libs_present": libs,
|
| 149 |
+
"acceleration_dependencies_ready": acceleration_dependencies_ready,
|
| 150 |
+
"acceleration_implementation_wired": False,
|
| 151 |
+
"execution_evidence": None,
|
| 152 |
"honest_note": (
|
| 153 |
+
"Pure-Python reference implementation executed: Jacobi eigensolver plus "
|
| 154 |
+
"pure-Python Vietoris-Rips β0/β1. GPU reachability and importable RAPIDS "
|
| 155 |
+
"dependencies indicate readiness only. The accelerated cuML/cuPy/Ripser++ "
|
| 156 |
+
"implementation is ROADMAP and cannot be labeled MEASURED until a distinct "
|
| 157 |
+
"device-executed path emits execution evidence."),
|
| 158 |
}
|
| 159 |
|
| 160 |
|
|
|
|
| 768 |
"config": "vLLM --tensor-parallel-size 2 shards ONE larger model across a-11-oy.com GPU + RTX 4000",
|
| 769 |
"fits": "e.g. Qwen3-32B comfortably, or a quantized Nemotron-3-Super across combined VRAM",
|
| 770 |
"gpus": [per_gpu("a-11-oy.com GPU"), per_gpu("NVIDIA RTX 4000 (Ada, ~20GB)")],
|
| 771 |
+
"label": "LIVE_REACHABLE" if reachable else "ROADMAP",
|
| 772 |
+
"execution_evidence": None,
|
| 773 |
},
|
| 774 |
{
|
| 775 |
"tier": "sovereign-local · ROLE-SPLIT (recommended for agent loops)",
|
|
|
|
| 780 |
"fits": "keeps the main GPU from stalling on inline review/draft — best fit for our agent+Auto-Review arch",
|
| 781 |
"gpus": [per_gpu("a-11-oy.com GPU · primary model"),
|
| 782 |
per_gpu("RTX 4000 · classifier+draft+embeddings")],
|
| 783 |
+
"label": "LIVE_REACHABLE" if reachable else "ROADMAP",
|
| 784 |
+
"execution_evidence": None,
|
| 785 |
},
|
| 786 |
{
|
| 787 |
"tier": "cloud · NVIDIA NIM (Nemotron 3 Ultra) — frontier/hard tier",
|
|
@@ -50,13 +50,14 @@ import math
|
|
| 50 |
import os
|
| 51 |
import threading
|
| 52 |
import time
|
| 53 |
-
import urllib.request as _urllib_request
|
| 54 |
from datetime import datetime, timezone
|
| 55 |
from typing import Any
|
| 56 |
|
| 57 |
from fastapi import FastAPI, Request
|
| 58 |
from fastapi.responses import JSONResponse
|
| 59 |
|
|
|
|
|
|
|
| 60 |
DOCTRINE = "v11"
|
| 61 |
_KERNEL = "c7c0ba17"
|
| 62 |
_LAMBDA_FLOOR = 0.90
|
|
@@ -75,6 +76,17 @@ _SOVEREIGN_PROVENANCE = "SZL sovereign (Ollama, local, Doctrine-v11 system promp
|
|
| 75 |
# the node answers this request; otherwise UNAVAILABLE (never SIMULATED/fabricated).
|
| 76 |
_LABEL_LIVE = "LIVE"
|
| 77 |
_LABEL_UNAVAILABLE = "UNAVAILABLE"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
# ─────────────────────────────────────────────────────────────────────────────
|
| 80 |
# THE CANONICAL LLM ROSTER — a11oy is the hub; every model lives here.
|
|
@@ -413,6 +425,11 @@ _SOVEREIGN_ENV = "SZL_LOCAL_LLM_URL"
|
|
| 413 |
# SZL_LOCAL_LLM_URL). Never fabricates reachability — a live call still proves it.
|
| 414 |
# See box-scripts/litellm_config.yaml + research/SOVEREIGN_MESH_RUNBOOK.md.
|
| 415 |
_GATEWAY_ENV = "A11OY_SOVEREIGN_GATEWAY_URL"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
# Optional bearer for a bearer-protected gateway (LiteLLM master_key). The SECRET
|
| 417 |
# is NEVER logged or returned — only attached as an Authorization header on the
|
| 418 |
# guarded outbound call. Falls back to SZL_LOCAL_LLM_KEY. Unset => no header.
|
|
@@ -443,27 +460,38 @@ _SOVEREIGN_DEFAULT_URL = "http://localhost:11434/v1"
|
|
| 443 |
def _sovereign_base() -> str:
|
| 444 |
"""Resolve the sovereign base URL from env.
|
| 445 |
|
| 446 |
-
Prefers the
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
(
|
| 450 |
-
|
|
|
|
| 451 |
trailing `/v1` back to the Ollama root for native /api calls, so either form
|
| 452 |
(`.../11434` or `.../11434/v1`) works. This is a guarded preference only — it
|
| 453 |
never asserts the endpoint is reachable; a live call still proves it.
|
| 454 |
"""
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 460 |
|
| 461 |
|
| 462 |
def _sovereign_env_present() -> bool:
|
| 463 |
-
"""True only when
|
| 464 |
-
|
| 465 |
-
return bool((os.environ.get(_GATEWAY_ENV, "") or "").strip()
|
| 466 |
-
or (os.environ.get(_SOVEREIGN_ENV, "") or "").strip())
|
| 467 |
|
| 468 |
|
| 469 |
def _ollama_root(base: str) -> str:
|
|
@@ -489,10 +517,78 @@ def _sovereign_auth_header() -> dict[str, str]:
|
|
| 489 |
|
| 490 |
|
| 491 |
def _sovereign_model_slug() -> str:
|
| 492 |
-
"""
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 496 |
|
| 497 |
|
| 498 |
def _http_json(url: str, *, method: str = "GET", body: bytes | None = None,
|
|
@@ -505,17 +601,12 @@ def _http_json(url: str, *, method: str = "GET", body: bytes | None = None,
|
|
| 505 |
headers["Content-Type"] = "application/json"
|
| 506 |
# Optional bearer for a bearer-protected gateway (LiteLLM). Secret never logged.
|
| 507 |
headers.update(_sovereign_auth_header())
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
raw = r.read().decode("utf-8", "replace")
|
| 515 |
-
doc = json.loads(raw)
|
| 516 |
-
return doc, None
|
| 517 |
-
except Exception as exc: # noqa: BLE001 — unreachable/timeout => honest OFFLINE
|
| 518 |
-
return None, "node unreachable: %s" % (str(exc)[:160])
|
| 519 |
|
| 520 |
|
| 521 |
def sovereign_probe(base: str = "", timeout: float | None = None) -> dict[str, Any]:
|
|
@@ -530,6 +621,8 @@ def sovereign_probe(base: str = "", timeout: float | None = None) -> dict[str, A
|
|
| 530 |
env_present = _sovereign_env_present()
|
| 531 |
out: dict[str, Any] = {
|
| 532 |
"env_var": _SOVEREIGN_ENV,
|
|
|
|
|
|
|
| 533 |
"env_present": env_present,
|
| 534 |
"base_url": base or None,
|
| 535 |
"live": False,
|
|
@@ -585,20 +678,41 @@ def sovereign_generate(prompt: str, base: str = "", model: str = "",
|
|
| 585 |
native /api/generate first, then OpenAI-compatible /v1/chat/completions.
|
| 586 |
"""
|
| 587 |
base = (base or _sovereign_base())
|
| 588 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 589 |
to = _SOVEREIGN_GEN_TIMEOUT_S if timeout is None else float(timeout)
|
| 590 |
res: dict[str, Any] = {
|
| 591 |
"wired": False, "live": False, "text": None, "model": model,
|
|
|
|
|
|
|
|
|
|
| 592 |
"api_style": None, "base_url": base or None, "env_var": _SOVEREIGN_ENV,
|
| 593 |
"env_present": _sovereign_env_present(), "note": "",
|
| 594 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 595 |
b = _ollama_root(base)
|
| 596 |
# 1) ollama native /api/generate
|
| 597 |
gen_url = b + "/api/generate"
|
| 598 |
body = json.dumps({"model": model, "prompt": prompt, "stream": False}).encode("utf-8")
|
| 599 |
doc, err = _http_json(gen_url, method="POST", body=body, timeout=to)
|
| 600 |
if isinstance(doc, dict) and isinstance(doc.get("response"), str):
|
| 601 |
-
res.update({"wired": True, "live": True, "
|
|
|
|
| 602 |
"api_style": "ollama /api/generate",
|
| 603 |
"note": "REAL local generation (ollama /api/generate) THIS request."})
|
| 604 |
for k in ("eval_count", "prompt_eval_count", "total_duration"):
|
|
@@ -617,7 +731,8 @@ def sovereign_generate(prompt: str, base: str = "", model: str = "",
|
|
| 617 |
except Exception: # noqa: BLE001 — malformed => honest stub
|
| 618 |
txt = None
|
| 619 |
if isinstance(txt, str):
|
| 620 |
-
res.update({"wired": True, "live": True, "
|
|
|
|
| 621 |
"api_style": "openai /v1/chat/completions",
|
| 622 |
"note": "REAL local generation (OpenAI-compatible /v1) THIS request."})
|
| 623 |
if isinstance(doc2.get("usage"), dict):
|
|
@@ -764,7 +879,9 @@ def sovereign_mesh_generate(prompt: str, timeout: float | None = None) -> dict[s
|
|
| 764 |
sel = matrix.get("selected")
|
| 765 |
res: dict[str, Any] = {
|
| 766 |
"wired": False, "live": False, "text": None,
|
| 767 |
-
"
|
|
|
|
|
|
|
| 768 |
"base_url": None, "role": None, "node_index": None,
|
| 769 |
"matrix": matrix, "note": "",
|
| 770 |
}
|
|
@@ -773,9 +890,23 @@ def sovereign_mesh_generate(prompt: str, timeout: float | None = None) -> dict[s
|
|
| 773 |
"%s" % matrix.get("note", ""))
|
| 774 |
return res
|
| 775 |
base = sel["base_url"]
|
| 776 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 777 |
res.update({
|
| 778 |
"wired": bool(gen.get("wired")), "live": bool(gen.get("live")),
|
|
|
|
| 779 |
"text": gen.get("text"), "model": gen.get("model"),
|
| 780 |
"api_style": gen.get("api_style"), "base_url": base,
|
| 781 |
"role": sel.get("role"), "node_index": sel.get("index"),
|
|
@@ -910,48 +1041,114 @@ def _enrich_model(m: dict, *, probe_local: bool = False) -> dict:
|
|
| 910 |
if model_id in (_SOVEREIGN_LEGACY_ID, _SOVEREIGN_BACKEND_ID) or env_var == _SOVEREIGN_ENV:
|
| 911 |
base = _sovereign_base()
|
| 912 |
env_present = _sovereign_env_present()
|
| 913 |
-
#
|
| 914 |
-
#
|
| 915 |
-
|
| 916 |
-
out["
|
| 917 |
-
out["
|
|
|
|
| 918 |
out["provider"] = m.get("provider", _SOVEREIGN_PROVENANCE)
|
| 919 |
-
out["env_used"] = _SOVEREIGN_ENV
|
| 920 |
out["env_present"] = env_present
|
| 921 |
out["base_url"] = base or m.get("api_base")
|
| 922 |
out["is_local"] = True
|
| 923 |
out["own_metal"] = True
|
| 924 |
# Default (no probe): honest UNAVAILABLE until proven live this request.
|
| 925 |
out["honest_stub"] = True
|
| 926 |
-
out["label"] =
|
| 927 |
out["reachable"] = False
|
|
|
|
|
|
|
|
|
|
|
|
|
| 928 |
if probe_local:
|
| 929 |
probe = sovereign_probe(base)
|
| 930 |
live = bool(probe.get("live"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 931 |
out["local_live"] = live
|
| 932 |
out["reachable"] = live
|
| 933 |
out["local_models"] = probe.get("models", [])
|
| 934 |
out["local_probe_note"] = probe.get("note", "")
|
| 935 |
out["api_style"] = probe.get("api_style")
|
| 936 |
-
|
| 937 |
-
out["
|
| 938 |
-
out["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 939 |
return out
|
| 940 |
|
| 941 |
-
|
| 942 |
-
out["api_key_wired"] =
|
| 943 |
-
out["
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 944 |
out["provider"] = m.get("provider")
|
| 945 |
out["env_used"] = env_var or None
|
| 946 |
-
out["env_present"] =
|
| 947 |
out["base_url"] = m.get("api_base") or m.get("base_url")
|
| 948 |
out["is_local"] = bool(m.get("open_weight"))
|
| 949 |
-
|
| 950 |
-
|
| 951 |
-
if m.get("open_weight"):
|
| 952 |
-
out["honest_stub"] = bool(m.get("honest_stub", True))
|
| 953 |
-
else:
|
| 954 |
-
out["honest_stub"] = not wired
|
| 955 |
return out
|
| 956 |
|
| 957 |
def _seed_forum() -> None:
|
|
@@ -959,7 +1156,9 @@ def _seed_forum() -> None:
|
|
| 959 |
_forum_append({
|
| 960 |
"ts": _now(), "source": "a11oy", "event": "registry_boot",
|
| 961 |
"model_count": len(MODEL_REGISTRY), "doctrine": DOCTRINE,
|
| 962 |
-
"note": "a11oy
|
|
|
|
|
|
|
| 963 |
})
|
| 964 |
_forum_append({
|
| 965 |
"ts": _now(), "source": "operator", "event": "forum_join",
|
|
@@ -990,15 +1189,23 @@ def register(app: FastAPI) -> dict:
|
|
| 990 |
do_probe = bool(probe)
|
| 991 |
models = [_enrich_model(m, probe_local=do_probe) for m in MODEL_REGISTRY]
|
| 992 |
wired = [m for m in models if m.get("wired")]
|
|
|
|
|
|
|
|
|
|
| 993 |
badges = [{
|
| 994 |
"model_id": m["model_id"],
|
| 995 |
"wired": bool(m.get("wired")),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 996 |
"provider": m.get("provider"),
|
| 997 |
"env_used": m.get("env_used"),
|
| 998 |
"base_url": m.get("base_url"),
|
| 999 |
"honest_stub": bool(m.get("honest_stub", True)),
|
| 1000 |
"is_local": bool(m.get("is_local")),
|
| 1001 |
-
**({"label": m.get("label"),
|
| 1002 |
"own_metal": bool(m.get("own_metal"))} if m.get("own_metal") else {}),
|
| 1003 |
} for m in models]
|
| 1004 |
all_stub = (len(wired) == 0)
|
|
@@ -1008,7 +1215,11 @@ def register(app: FastAPI) -> dict:
|
|
| 1008 |
_sov_badge = next((m for m in models if m.get("model_id") == _SOVEREIGN_BACKEND_ID), None)
|
| 1009 |
sovereign_snapshot = {
|
| 1010 |
"backend_id": _SOVEREIGN_BACKEND_ID,
|
| 1011 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1012 |
"provider": _SOVEREIGN_PROVENANCE,
|
| 1013 |
"url": _sovereign_base(),
|
| 1014 |
"env_present": _sovereign_env_present(),
|
|
@@ -1016,6 +1227,12 @@ def register(app: FastAPI) -> dict:
|
|
| 1016 |
"reachable": (bool(_sov_badge.get("reachable")) if (do_probe and _sov_badge) else None),
|
| 1017 |
"label": (_sov_badge.get("label") if (do_probe and _sov_badge)
|
| 1018 |
else "UNPROBED (pass ?probe=1 for THIS-request reachability)"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1019 |
"route_order": "own-metal/sovereign FIRST (when reachable) → free → paid",
|
| 1020 |
"health_endpoint": "/api/a11oy/v1/llm/sovereign/health",
|
| 1021 |
}
|
|
@@ -1026,6 +1243,15 @@ def register(app: FastAPI) -> dict:
|
|
| 1026 |
"model_count": len(models),
|
| 1027 |
"wired_count": len(wired),
|
| 1028 |
"wired_model_ids": [m["model_id"] for m in wired],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1029 |
"models": models,
|
| 1030 |
"badges": badges,
|
| 1031 |
"tier_map": {
|
|
@@ -1043,11 +1269,12 @@ def register(app: FastAPI) -> dict:
|
|
| 1043 |
"doctrine": DOCTRINE,
|
| 1044 |
"kernel_commit": _KERNEL,
|
| 1045 |
"honest_note": (
|
| 1046 |
-
("
|
| 1047 |
-
"
|
|
|
|
| 1048 |
if all_stub else
|
| 1049 |
-
("
|
| 1050 |
-
"
|
| 1051 |
% len(wired))),
|
| 1052 |
})
|
| 1053 |
|
|
@@ -1177,17 +1404,44 @@ def register(app: FastAPI) -> dict:
|
|
| 1177 |
_want_sovereign = _explicit_sovereign or _offline_pref or _own_metal_first
|
| 1178 |
if _want_sovereign:
|
| 1179 |
gen = _mesh_gen
|
| 1180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1181 |
# Prefer the first-class Wave-M backend id; fall back to legacy alias.
|
| 1182 |
sov_model = (_MODEL_BY_ID.get(_SOVEREIGN_BACKEND_ID)
|
| 1183 |
or _MODEL_BY_ID.get(_SOVEREIGN_LEGACY_ID)
|
| 1184 |
or MODEL_REGISTRY[0])
|
| 1185 |
sov_enriched = _enrich_model(sov_model)
|
| 1186 |
-
sov_enriched
|
| 1187 |
-
sov_enriched["
|
| 1188 |
-
sov_enriched["local_live"] =
|
| 1189 |
-
sov_enriched["
|
| 1190 |
-
sov_enriched["
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1191 |
if _explicit_sovereign:
|
| 1192 |
_why = "explicit request"
|
| 1193 |
elif _own_metal_first:
|
|
@@ -1195,11 +1449,15 @@ def register(app: FastAPI) -> dict:
|
|
| 1195 |
else:
|
| 1196 |
_why = "offline preference, no cloud key wired"
|
| 1197 |
sov_reason = "%s selected (%s); " % (sov_model.get("model_id"), _why)
|
| 1198 |
-
if
|
| 1199 |
-
sov_reason += ("own-metal-first node %s (role=%s)
|
| 1200 |
-
"
|
| 1201 |
% (gen.get("base_url"), gen.get("role")))
|
| 1202 |
response_text = gen.get("text") or ""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1203 |
elif _mesh_reachable:
|
| 1204 |
sov_reason += ("node %s reachable but did not generate live — honest "
|
| 1205 |
"UNAVAILABLE (never fabricate)." % gen.get("base_url"))
|
|
@@ -1232,10 +1490,16 @@ def register(app: FastAPI) -> dict:
|
|
| 1232 |
"model_display": sov_model.get("display_name"),
|
| 1233 |
"reason": sov_reason, "task_hint": task_hint,
|
| 1234 |
"own_metal_first": bool(_own_metal_first),
|
| 1235 |
-
"
|
| 1236 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1237 |
"api_key_wired": _sovereign_env_present(),
|
| 1238 |
-
"local_live":
|
| 1239 |
"local_api_style": gen.get("api_style"),
|
| 1240 |
"local_base_url": gen.get("base_url"),
|
| 1241 |
"mesh_node_count": matrix.get("node_count", 0),
|
|
@@ -1243,6 +1507,8 @@ def register(app: FastAPI) -> dict:
|
|
| 1243 |
"mesh_selected": matrix.get("selected"),
|
| 1244 |
"selected_role": gen.get("role"),
|
| 1245 |
"selected_base_url": gen.get("base_url"),
|
|
|
|
|
|
|
| 1246 |
"doctrine": DOCTRINE, "kernel_commit": _KERNEL,
|
| 1247 |
"conjecture_note": "Λ = Conjecture 1 — NOT a theorem. CAUCHY_ND sorry open.",
|
| 1248 |
}
|
|
@@ -1252,14 +1518,20 @@ def register(app: FastAPI) -> dict:
|
|
| 1252 |
"response": response_text,
|
| 1253 |
"model_selected": sov_enriched,
|
| 1254 |
"lambda_receipt": sov_receipt,
|
| 1255 |
-
"label":
|
| 1256 |
-
"reachable":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1257 |
"routed_via": "%s via sovereign_mesh (%s)" % (
|
| 1258 |
sov_model.get("model_id"),
|
| 1259 |
-
gen.get("api_style") if
|
| 1260 |
"local": {k: gen.get(k) for k in
|
| 1261 |
-
("wired", "live", "api_style", "base_url", "role",
|
| 1262 |
-
"node_index", "model", "
|
|
|
|
| 1263 |
if k in gen},
|
| 1264 |
"sovereign_mesh": matrix,
|
| 1265 |
"doctrine": DOCTRINE,
|
|
@@ -1305,6 +1577,13 @@ def register(app: FastAPI) -> dict:
|
|
| 1305 |
except Exception:
|
| 1306 |
pass
|
| 1307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1308 |
receipt = {
|
| 1309 |
"schema": "szl.llm_route.lambda_receipt/v1",
|
| 1310 |
"ts": _now(),
|
|
@@ -1320,6 +1599,13 @@ def register(app: FastAPI) -> dict:
|
|
| 1320 |
"model_weight_sha256": mw_sha,
|
| 1321 |
"model_weight_method": mw_method,
|
| 1322 |
"api_key_wired": enriched["api_key_wired"],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1323 |
"doctrine": DOCTRINE,
|
| 1324 |
"kernel_commit": _KERNEL,
|
| 1325 |
"conjecture_note": "Λ = Conjecture 1 — NOT a theorem. CAUCHY_ND sorry open.",
|
|
@@ -1328,7 +1614,11 @@ def register(app: FastAPI) -> dict:
|
|
| 1328 |
# Emit honest response (stub when no key)
|
| 1329 |
if enriched["api_key_wired"]:
|
| 1330 |
# Real call would go here — key present but routing call not implemented
|
| 1331 |
-
response_text =
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1332 |
else:
|
| 1333 |
response_text = (
|
| 1334 |
f"[HONEST STUB] Would route to {selected_model['display_name']} "
|
|
@@ -1477,20 +1767,35 @@ def register(app: FastAPI) -> dict:
|
|
| 1477 |
base = _sovereign_base()
|
| 1478 |
primary_probe = sovereign_probe(base)
|
| 1479 |
env_present = bool(primary_probe.get("env_present"))
|
| 1480 |
-
wired = env_present
|
| 1481 |
any_reachable = bool(matrix.get("any_reachable"))
|
| 1482 |
# Primary-node reachability (Wave-M compact contract mirrors the primary).
|
| 1483 |
reachable = bool(primary_probe.get("live"))
|
| 1484 |
-
|
| 1485 |
-
|
| 1486 |
-
|
| 1487 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1488 |
return JSONResponse({
|
| 1489 |
# ── Wave-M required compact contract ──
|
| 1490 |
# `model` = canonical sovereign model tag; `configured_model` (below)
|
| 1491 |
# is the runtime-overridable ollama tag the node is asked to serve.
|
| 1492 |
"reachable": reachable,
|
| 1493 |
-
"model":
|
| 1494 |
"url": base,
|
| 1495 |
"provider": _SOVEREIGN_PROVENANCE,
|
| 1496 |
"label": label,
|
|
@@ -1501,6 +1806,16 @@ def register(app: FastAPI) -> dict:
|
|
| 1501 |
"model_id": _SOVEREIGN_BACKEND_ID,
|
| 1502 |
"legacy_alias": _SOVEREIGN_LEGACY_ID,
|
| 1503 |
"model_slug": _SOVEREIGN_MODEL_TAG,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1504 |
# ── Mesh (multi-node) reachability matrix (Wave N, Dev 3) ──
|
| 1505 |
"sovereign_status": sovereign_status, # honest label: LIVE | UNAVAILABLE (mesh-wide)
|
| 1506 |
"mesh": matrix,
|
|
@@ -1510,17 +1825,23 @@ def register(app: FastAPI) -> dict:
|
|
| 1510 |
"selected_node": matrix.get("selected"),
|
| 1511 |
"own_metal_first": True,
|
| 1512 |
"fallthrough_to_cloud": (not any_reachable),
|
| 1513 |
-
"env_vars": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1514 |
# ── Backward-compatible single-node (primary) fields ──
|
| 1515 |
"env_var": _SOVEREIGN_ENV,
|
| 1516 |
"env_present": env_present,
|
| 1517 |
-
"wired":
|
| 1518 |
"live": reachable, # primary-node THIS-request liveness (== reachable)
|
| 1519 |
-
"honest_stub": not
|
| 1520 |
"base_url": base,
|
| 1521 |
"api_style": primary_probe.get("api_style"),
|
| 1522 |
"served_models": primary_probe.get("models", []),
|
| 1523 |
-
"configured_model": _sovereign_model_slug(),
|
| 1524 |
"probed": primary_probe.get("probed", []),
|
| 1525 |
"probe_ua": "browser-UA (Cloudflare-front safe)",
|
| 1526 |
"note": matrix.get("note", ""),
|
|
@@ -1547,6 +1868,14 @@ def register(app: FastAPI) -> dict:
|
|
| 1547 |
"provider": provider,
|
| 1548 |
"env_var": env_var, # NAME ONLY — never the secret value
|
| 1549 |
"key_present": present,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1550 |
})
|
| 1551 |
if present:
|
| 1552 |
seen_present.add(provider)
|
|
@@ -1570,6 +1899,21 @@ def register(app: FastAPI) -> dict:
|
|
| 1570 |
_matrix = sovereign_mesh_matrix()
|
| 1571 |
_any = bool(_matrix.get("any_reachable"))
|
| 1572 |
_sel = _matrix.get("selected") or {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1573 |
_mesh_summary = {
|
| 1574 |
"node_count": _matrix.get("node_count", 0),
|
| 1575 |
"reachable_count": _matrix.get("reachable_count", 0),
|
|
@@ -1586,7 +1930,17 @@ def register(app: FastAPI) -> dict:
|
|
| 1586 |
"nodes_env": _SOVEREIGN_NODES_ENV,
|
| 1587 |
"env_present": _sovereign_env_present(),
|
| 1588 |
"live": _any, "reachable": _any,
|
| 1589 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1590 |
"served_models": _sel.get("served_models", []),
|
| 1591 |
"note": _matrix.get("note", ""),
|
| 1592 |
}
|
|
@@ -1596,7 +1950,10 @@ def register(app: FastAPI) -> dict:
|
|
| 1596 |
"env_var": _SOVEREIGN_ENV, "base_url": base or None,
|
| 1597 |
"nodes_env": _SOVEREIGN_NODES_ENV,
|
| 1598 |
"env_present": _sovereign_env_present(), "live": None,
|
| 1599 |
-
"reachable": None, "
|
|
|
|
|
|
|
|
|
|
| 1600 |
"note": "pass ?probe=1 to ping the mesh for THIS-request liveness",
|
| 1601 |
}
|
| 1602 |
|
|
@@ -1607,16 +1964,18 @@ def register(app: FastAPI) -> dict:
|
|
| 1607 |
"role": "router key/liveness status — provider NAMES only, never secrets",
|
| 1608 |
"providers": providers,
|
| 1609 |
"provider_keys_present": provider_keys_present,
|
| 1610 |
-
"
|
|
|
|
|
|
|
| 1611 |
"code_agent_credential": code_key_public,
|
| 1612 |
"local_nodes": [local_node],
|
| 1613 |
"sovereign_mesh": _mesh_summary,
|
| 1614 |
"any_cloud_key_present": len(provider_keys_present) > 0,
|
| 1615 |
"doctrine": DOCTRINE,
|
| 1616 |
"kernel_commit": _KERNEL,
|
| 1617 |
-
"honest_note": ("Presence is a real os.environ check THIS request
|
| 1618 |
-
"
|
| 1619 |
-
"
|
| 1620 |
})
|
| 1621 |
|
| 1622 |
return {
|
|
|
|
| 50 |
import os
|
| 51 |
import threading
|
| 52 |
import time
|
|
|
|
| 53 |
from datetime import datetime, timezone
|
| 54 |
from typing import Any
|
| 55 |
|
| 56 |
from fastapi import FastAPI, Request
|
| 57 |
from fastapi.responses import JSONResponse
|
| 58 |
|
| 59 |
+
from szl_provider_http import http_json as _bounded_http_json
|
| 60 |
+
|
| 61 |
DOCTRINE = "v11"
|
| 62 |
_KERNEL = "c7c0ba17"
|
| 63 |
_LAMBDA_FLOOR = 0.90
|
|
|
|
| 76 |
# the node answers this request; otherwise UNAVAILABLE (never SIMULATED/fabricated).
|
| 77 |
_LABEL_LIVE = "LIVE"
|
| 78 |
_LABEL_UNAVAILABLE = "UNAVAILABLE"
|
| 79 |
+
_STATE_OFFLINE_UNTIL_KEYED = "OFFLINE_UNTIL_KEYED"
|
| 80 |
+
_STATE_CONFIGURED_UNVERIFIED = "CONFIGURED_UNVERIFIED"
|
| 81 |
+
_STATE_UNAVAILABLE = "UNAVAILABLE"
|
| 82 |
+
_STATE_REACHABLE_MODEL_MISMATCH = "REACHABLE_MODEL_MISMATCH"
|
| 83 |
+
_STATE_REACHABLE_UNRECEIPTED = "REACHABLE_UNRECEIPTED"
|
| 84 |
+
_STATE_LIVE_RECEIPTED = "LIVE_RECEIPTED"
|
| 85 |
+
_SOVEREIGN_MODEL_ALIASES = (
|
| 86 |
+
_SOVEREIGN_MODEL_TAG,
|
| 87 |
+
"szl-sovereign:latest",
|
| 88 |
+
"szl1:latest",
|
| 89 |
+
)
|
| 90 |
|
| 91 |
# ─────────────────────────────────────────────────────────────────────────────
|
| 92 |
# THE CANONICAL LLM ROSTER — a11oy is the hub; every model lives here.
|
|
|
|
| 425 |
# SZL_LOCAL_LLM_URL). Never fabricates reachability — a live call still proves it.
|
| 426 |
# See box-scripts/litellm_config.yaml + research/SOVEREIGN_MESH_RUNBOOK.md.
|
| 427 |
_GATEWAY_ENV = "A11OY_SOVEREIGN_GATEWAY_URL"
|
| 428 |
+
# Code/Forge uses these names for the endpoint that actually serves turns. The
|
| 429 |
+
# global health rollup is backed by this registry, so it must resolve the same
|
| 430 |
+
# endpoint instead of silently probing the legacy localhost default. Ordered
|
| 431 |
+
# exactly as a11oy_code_orchestrator._sovereign_base_url().
|
| 432 |
+
_CODE_SOVEREIGN_ENVS = ("A11OY_BRAIN_URL", "A11OY_MODEL_BASE_URL")
|
| 433 |
# Optional bearer for a bearer-protected gateway (LiteLLM master_key). The SECRET
|
| 434 |
# is NEVER logged or returned — only attached as an Authorization header on the
|
| 435 |
# guarded outbound call. Falls back to SZL_LOCAL_LLM_KEY. Unset => no header.
|
|
|
|
| 460 |
def _sovereign_base() -> str:
|
| 461 |
"""Resolve the sovereign base URL from env.
|
| 462 |
|
| 463 |
+
Prefers the Code/Forge serving endpoint (A11OY_BRAIN_URL then
|
| 464 |
+
A11OY_MODEL_BASE_URL) so the global health rollup observes the same endpoint
|
| 465 |
+
that actually serves turns. Falls back to the unified mesh gateway
|
| 466 |
+
(A11OY_SOVEREIGN_GATEWAY_URL), the legacy single-node SZL_LOCAL_LLM_URL, then
|
| 467 |
+
the OpenAI-compatible Tower endpoint (http://localhost:11434/v1). The
|
| 468 |
+
probe/generate paths normalise a
|
| 469 |
trailing `/v1` back to the Ollama root for native /api calls, so either form
|
| 470 |
(`.../11434` or `.../11434/v1`) works. This is a guarded preference only — it
|
| 471 |
never asserts the endpoint is reachable; a live call still proves it.
|
| 472 |
"""
|
| 473 |
+
for env_name in (*_CODE_SOVEREIGN_ENVS, _GATEWAY_ENV, _SOVEREIGN_ENV):
|
| 474 |
+
val = (os.environ.get(env_name, "") or "").strip()
|
| 475 |
+
if val:
|
| 476 |
+
return val.rstrip("/")
|
| 477 |
+
return _SOVEREIGN_DEFAULT_URL
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
def _sovereign_env_used() -> str | None:
|
| 481 |
+
"""Return the endpoint env NAME selected by :func:`_sovereign_base`.
|
| 482 |
+
|
| 483 |
+
The value is deliberately never returned or logged here. ``None`` means
|
| 484 |
+
the guarded localhost default is being probed without operator intent.
|
| 485 |
+
"""
|
| 486 |
+
for env_name in (*_CODE_SOVEREIGN_ENVS, _GATEWAY_ENV, _SOVEREIGN_ENV):
|
| 487 |
+
if (os.environ.get(env_name, "") or "").strip():
|
| 488 |
+
return env_name
|
| 489 |
+
return None
|
| 490 |
|
| 491 |
|
| 492 |
def _sovereign_env_present() -> bool:
|
| 493 |
+
"""True only when an accepted serving-endpoint env was explicitly set."""
|
| 494 |
+
return _sovereign_env_used() is not None
|
|
|
|
|
|
|
| 495 |
|
| 496 |
|
| 497 |
def _ollama_root(base: str) -> str:
|
|
|
|
| 517 |
|
| 518 |
|
| 519 |
def _sovereign_model_slug() -> str:
|
| 520 |
+
"""Requested model tag, without pretending a legacy default is installed."""
|
| 521 |
+
return (os.environ.get("SZL_LOCAL_LLM_MODEL", "") or "").strip()
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
def _reconcile_sovereign_model(served_models: list[str], requested: str = "") -> dict[str, Any]:
|
| 525 |
+
"""Resolve the exact tag that can be executed on a probed local node.
|
| 526 |
+
|
| 527 |
+
An explicit SZL_LOCAL_LLM_MODEL is fail-closed: if the node does not report
|
| 528 |
+
that exact tag, no alternate is silently substituted. Without an explicit
|
| 529 |
+
tag we may select only a declared SZL alias, never an arbitrary first model.
|
| 530 |
+
"""
|
| 531 |
+
served = [str(m).strip() for m in served_models if str(m).strip()]
|
| 532 |
+
served_set = set(served)
|
| 533 |
+
explicit = (requested or _sovereign_model_slug()).strip()
|
| 534 |
+
if explicit:
|
| 535 |
+
if explicit in served_set:
|
| 536 |
+
return {"requested_model": explicit, "selected_model": explicit,
|
| 537 |
+
"model_ready": True, "selection_basis": "explicit exact match",
|
| 538 |
+
"served_models": served}
|
| 539 |
+
return {"requested_model": explicit, "selected_model": None,
|
| 540 |
+
"model_ready": False,
|
| 541 |
+
"selection_basis": "explicit model not present in served model list",
|
| 542 |
+
"served_models": served}
|
| 543 |
+
for alias in _SOVEREIGN_MODEL_ALIASES:
|
| 544 |
+
if alias in served_set:
|
| 545 |
+
return {"requested_model": None, "selected_model": alias,
|
| 546 |
+
"model_ready": True,
|
| 547 |
+
"selection_basis": "declared SZL alias exact match",
|
| 548 |
+
"served_models": served}
|
| 549 |
+
return {"requested_model": None, "selected_model": None,
|
| 550 |
+
"model_ready": False,
|
| 551 |
+
"selection_basis": "no explicit model and no declared SZL alias is served",
|
| 552 |
+
"served_models": served}
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
def _inference_receipt_state(model: str = "") -> dict[str, Any]:
|
| 556 |
+
"""Read durable successful-inference proof without making a network call."""
|
| 557 |
+
try:
|
| 558 |
+
import szl_governed_infer as _gi
|
| 559 |
+
status = _gi.inference_receipt_status(model)
|
| 560 |
+
return dict(status)
|
| 561 |
+
except Exception as exc: # honest read failure; never create proof on a GET
|
| 562 |
+
return {"inference_receipted": False, "successful_receipt_count": 0,
|
| 563 |
+
"total_receipt_count": 0, "chain_ok": False,
|
| 564 |
+
"latest_receipt_hash": None,
|
| 565 |
+
"reason": "receipt ledger unavailable: %s" % type(exc).__name__}
|
| 566 |
+
|
| 567 |
+
|
| 568 |
+
def _provider_state(*, configured: bool, reachable: bool, model_ready: bool,
|
| 569 |
+
inference_receipted: bool, requires_key: bool = False) -> dict[str, Any]:
|
| 570 |
+
"""Keep configuration, reachability, proof, and operation independent."""
|
| 571 |
+
operational = bool(reachable and model_ready and inference_receipted)
|
| 572 |
+
if operational:
|
| 573 |
+
state = _STATE_LIVE_RECEIPTED
|
| 574 |
+
elif requires_key and not configured:
|
| 575 |
+
state = _STATE_OFFLINE_UNTIL_KEYED
|
| 576 |
+
elif requires_key and configured:
|
| 577 |
+
state = _STATE_CONFIGURED_UNVERIFIED
|
| 578 |
+
elif not reachable:
|
| 579 |
+
state = _STATE_UNAVAILABLE
|
| 580 |
+
elif not model_ready:
|
| 581 |
+
state = _STATE_REACHABLE_MODEL_MISMATCH
|
| 582 |
+
else:
|
| 583 |
+
state = _STATE_REACHABLE_UNRECEIPTED
|
| 584 |
+
return {
|
| 585 |
+
"configured": bool(configured),
|
| 586 |
+
"reachable": bool(reachable),
|
| 587 |
+
"model_ready": bool(model_ready),
|
| 588 |
+
"inference_receipted": bool(inference_receipted),
|
| 589 |
+
"operational": operational,
|
| 590 |
+
"state": state,
|
| 591 |
+
}
|
| 592 |
|
| 593 |
|
| 594 |
def _http_json(url: str, *, method: str = "GET", body: bytes | None = None,
|
|
|
|
| 601 |
headers["Content-Type"] = "application/json"
|
| 602 |
# Optional bearer for a bearer-protected gateway (LiteLLM). Secret never logged.
|
| 603 |
headers.update(_sovereign_auth_header())
|
| 604 |
+
# Private/local targets are permitted only because this is the explicit
|
| 605 |
+
# operator-controlled sovereign path. Metadata/link-local targets remain
|
| 606 |
+
# denied; DNS and redirects are revalidated and the body/time are bounded.
|
| 607 |
+
return _bounded_http_json(
|
| 608 |
+
url, method=method, body=body, headers=headers, timeout=timeout,
|
| 609 |
+
max_response_bytes=1_048_576, max_redirects=2, allow_private=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 610 |
|
| 611 |
|
| 612 |
def sovereign_probe(base: str = "", timeout: float | None = None) -> dict[str, Any]:
|
|
|
|
| 621 |
env_present = _sovereign_env_present()
|
| 622 |
out: dict[str, Any] = {
|
| 623 |
"env_var": _SOVEREIGN_ENV,
|
| 624 |
+
"env_used": _sovereign_env_used(),
|
| 625 |
+
"accepted_endpoint_envs": [*_CODE_SOVEREIGN_ENVS, _GATEWAY_ENV, _SOVEREIGN_ENV],
|
| 626 |
"env_present": env_present,
|
| 627 |
"base_url": base or None,
|
| 628 |
"live": False,
|
|
|
|
| 678 |
native /api/generate first, then OpenAI-compatible /v1/chat/completions.
|
| 679 |
"""
|
| 680 |
base = (base or _sovereign_base())
|
| 681 |
+
requested_model = (model or _sovereign_model_slug()).strip()
|
| 682 |
+
resolution = None
|
| 683 |
+
if not model:
|
| 684 |
+
probe = sovereign_probe(base, timeout=min(
|
| 685 |
+
_SOVEREIGN_PROBE_TIMEOUT_S,
|
| 686 |
+
_SOVEREIGN_GEN_TIMEOUT_S if timeout is None else float(timeout)))
|
| 687 |
+
resolution = _reconcile_sovereign_model(
|
| 688 |
+
probe.get("models", []), requested=requested_model)
|
| 689 |
+
model = resolution.get("selected_model") or ""
|
| 690 |
+
else:
|
| 691 |
+
model = model.strip()
|
| 692 |
+
resolution = {"requested_model": requested_model or model,
|
| 693 |
+
"selected_model": model, "model_ready": bool(model),
|
| 694 |
+
"selection_basis": "pre-reconciled model from mesh probe"}
|
| 695 |
to = _SOVEREIGN_GEN_TIMEOUT_S if timeout is None else float(timeout)
|
| 696 |
res: dict[str, Any] = {
|
| 697 |
"wired": False, "live": False, "text": None, "model": model,
|
| 698 |
+
"generated": False, "inference_receipted": False,
|
| 699 |
+
"model_ready": bool(resolution.get("model_ready")),
|
| 700 |
+
"model_resolution": resolution,
|
| 701 |
"api_style": None, "base_url": base or None, "env_var": _SOVEREIGN_ENV,
|
| 702 |
"env_present": _sovereign_env_present(), "note": "",
|
| 703 |
}
|
| 704 |
+
if not model:
|
| 705 |
+
res["note"] = ("Sovereign endpoint may be reachable, but no executable model "
|
| 706 |
+
"tag reconciled against its served model list; generation denied.")
|
| 707 |
+
return res
|
| 708 |
b = _ollama_root(base)
|
| 709 |
# 1) ollama native /api/generate
|
| 710 |
gen_url = b + "/api/generate"
|
| 711 |
body = json.dumps({"model": model, "prompt": prompt, "stream": False}).encode("utf-8")
|
| 712 |
doc, err = _http_json(gen_url, method="POST", body=body, timeout=to)
|
| 713 |
if isinstance(doc, dict) and isinstance(doc.get("response"), str):
|
| 714 |
+
res.update({"wired": True, "live": True, "generated": True,
|
| 715 |
+
"text": doc["response"],
|
| 716 |
"api_style": "ollama /api/generate",
|
| 717 |
"note": "REAL local generation (ollama /api/generate) THIS request."})
|
| 718 |
for k in ("eval_count", "prompt_eval_count", "total_duration"):
|
|
|
|
| 731 |
except Exception: # noqa: BLE001 — malformed => honest stub
|
| 732 |
txt = None
|
| 733 |
if isinstance(txt, str):
|
| 734 |
+
res.update({"wired": True, "live": True, "generated": True,
|
| 735 |
+
"text": txt,
|
| 736 |
"api_style": "openai /v1/chat/completions",
|
| 737 |
"note": "REAL local generation (OpenAI-compatible /v1) THIS request."})
|
| 738 |
if isinstance(doc2.get("usage"), dict):
|
|
|
|
| 879 |
sel = matrix.get("selected")
|
| 880 |
res: dict[str, Any] = {
|
| 881 |
"wired": False, "live": False, "text": None,
|
| 882 |
+
"generated": False, "inference_receipted": False,
|
| 883 |
+
"model": None, "requested_model": _sovereign_model_slug() or None,
|
| 884 |
+
"model_ready": False, "model_resolution": None, "api_style": None,
|
| 885 |
"base_url": None, "role": None, "node_index": None,
|
| 886 |
"matrix": matrix, "note": "",
|
| 887 |
}
|
|
|
|
| 890 |
"%s" % matrix.get("note", ""))
|
| 891 |
return res
|
| 892 |
base = sel["base_url"]
|
| 893 |
+
resolution = _reconcile_sovereign_model(
|
| 894 |
+
sel.get("served_models", []), requested=_sovereign_model_slug())
|
| 895 |
+
res["model_resolution"] = resolution
|
| 896 |
+
res["model_ready"] = bool(resolution.get("model_ready"))
|
| 897 |
+
res["model"] = resolution.get("selected_model")
|
| 898 |
+
if not resolution.get("model_ready"):
|
| 899 |
+
res.update({"base_url": base, "role": sel.get("role"),
|
| 900 |
+
"node_index": sel.get("index")})
|
| 901 |
+
res["note"] = ("Node %s is reachable, but model reconciliation failed: %s. "
|
| 902 |
+
"Generation denied; no text or inference receipt fabricated."
|
| 903 |
+
% (base, resolution.get("selection_basis")))
|
| 904 |
+
return res
|
| 905 |
+
gen = sovereign_generate(prompt, base=base,
|
| 906 |
+
model=resolution["selected_model"], timeout=timeout)
|
| 907 |
res.update({
|
| 908 |
"wired": bool(gen.get("wired")), "live": bool(gen.get("live")),
|
| 909 |
+
"generated": bool(gen.get("generated")),
|
| 910 |
"text": gen.get("text"), "model": gen.get("model"),
|
| 911 |
"api_style": gen.get("api_style"), "base_url": base,
|
| 912 |
"role": sel.get("role"), "node_index": sel.get("index"),
|
|
|
|
| 1041 |
if model_id in (_SOVEREIGN_LEGACY_ID, _SOVEREIGN_BACKEND_ID) or env_var == _SOVEREIGN_ENV:
|
| 1042 |
base = _sovereign_base()
|
| 1043 |
env_present = _sovereign_env_present()
|
| 1044 |
+
# Backward-compatible api_key_wired means configuration only. `wired`
|
| 1045 |
+
# now means operational (successful durable inference proof), not intent.
|
| 1046 |
+
out["api_key_wired"] = env_present
|
| 1047 |
+
out["credential_configured"] = env_present
|
| 1048 |
+
out["configured"] = env_present
|
| 1049 |
+
out["wired"] = False
|
| 1050 |
out["provider"] = m.get("provider", _SOVEREIGN_PROVENANCE)
|
| 1051 |
+
out["env_used"] = _sovereign_env_used() or _SOVEREIGN_ENV
|
| 1052 |
out["env_present"] = env_present
|
| 1053 |
out["base_url"] = base or m.get("api_base")
|
| 1054 |
out["is_local"] = True
|
| 1055 |
out["own_metal"] = True
|
| 1056 |
# Default (no probe): honest UNAVAILABLE until proven live this request.
|
| 1057 |
out["honest_stub"] = True
|
| 1058 |
+
out["label"] = "UNPROBED"
|
| 1059 |
out["reachable"] = False
|
| 1060 |
+
out["model_ready"] = False
|
| 1061 |
+
out["inference_receipted"] = False
|
| 1062 |
+
out["operational"] = False
|
| 1063 |
+
out["state"] = "UNPROBED"
|
| 1064 |
if probe_local:
|
| 1065 |
probe = sovereign_probe(base)
|
| 1066 |
live = bool(probe.get("live"))
|
| 1067 |
+
resolution = _reconcile_sovereign_model(
|
| 1068 |
+
probe.get("models", []), requested=_sovereign_model_slug())
|
| 1069 |
+
selected_model = resolution.get("selected_model")
|
| 1070 |
+
receipt_state = (_inference_receipt_state(selected_model)
|
| 1071 |
+
if selected_model else
|
| 1072 |
+
{"inference_receipted": False,
|
| 1073 |
+
"successful_receipt_count": 0,
|
| 1074 |
+
"chain_ok": True,
|
| 1075 |
+
"latest_receipt_hash": None})
|
| 1076 |
+
state = _provider_state(
|
| 1077 |
+
configured=env_present,
|
| 1078 |
+
reachable=live,
|
| 1079 |
+
model_ready=bool(resolution.get("model_ready")),
|
| 1080 |
+
inference_receipted=bool(receipt_state.get("inference_receipted")))
|
| 1081 |
out["local_live"] = live
|
| 1082 |
out["reachable"] = live
|
| 1083 |
out["local_models"] = probe.get("models", [])
|
| 1084 |
out["local_probe_note"] = probe.get("note", "")
|
| 1085 |
out["api_style"] = probe.get("api_style")
|
| 1086 |
+
out["requested_model"] = resolution.get("requested_model")
|
| 1087 |
+
out["selected_model"] = selected_model
|
| 1088 |
+
out["model_resolution"] = resolution
|
| 1089 |
+
out["receipt_state"] = receipt_state
|
| 1090 |
+
out.update(state)
|
| 1091 |
+
out["wired"] = state["operational"]
|
| 1092 |
+
out["honest_stub"] = not state["operational"]
|
| 1093 |
+
out["label"] = state["state"]
|
| 1094 |
+
return out
|
| 1095 |
+
|
| 1096 |
+
if m.get("open_weight"):
|
| 1097 |
+
backend_live = False
|
| 1098 |
+
backend_note = "catalog-only model; no local backend receipt"
|
| 1099 |
+
if m.get("tier_band") == "demo_cpu":
|
| 1100 |
+
try:
|
| 1101 |
+
import szl_alloy_models as _alloy
|
| 1102 |
+
backend_live = bool(_alloy.backend_available())
|
| 1103 |
+
backend_note = (_alloy._LLAMA_ERR or
|
| 1104 |
+
"llama.cpp backend and GGUF are loadable")
|
| 1105 |
+
except Exception as exc:
|
| 1106 |
+
backend_note = "alloy backend unavailable: %s" % type(exc).__name__
|
| 1107 |
+
receipt_state = (_inference_receipt_state(model_id)
|
| 1108 |
+
if backend_live else
|
| 1109 |
+
{"inference_receipted": False,
|
| 1110 |
+
"successful_receipt_count": 0,
|
| 1111 |
+
"chain_ok": True,
|
| 1112 |
+
"latest_receipt_hash": None})
|
| 1113 |
+
state = _provider_state(
|
| 1114 |
+
configured=backend_live, reachable=backend_live,
|
| 1115 |
+
model_ready=backend_live,
|
| 1116 |
+
inference_receipted=bool(receipt_state.get("inference_receipted")))
|
| 1117 |
+
out.update(state)
|
| 1118 |
+
out["api_key_wired"] = False
|
| 1119 |
+
out["credential_configured"] = False
|
| 1120 |
+
out["wired"] = state["operational"]
|
| 1121 |
+
out["provider"] = m.get("provider")
|
| 1122 |
+
out["env_used"] = "A11OY_ALLOY_GGUF" if m.get("tier_band") == "demo_cpu" else None
|
| 1123 |
+
out["env_present"] = bool(os.environ.get("A11OY_ALLOY_GGUF", "").strip())
|
| 1124 |
+
out["base_url"] = None
|
| 1125 |
+
out["is_local"] = True
|
| 1126 |
+
out["runtime_available"] = backend_live
|
| 1127 |
+
out["receipt_state"] = receipt_state
|
| 1128 |
+
out["honest_stub"] = not state["operational"]
|
| 1129 |
+
out["label"] = state["state"]
|
| 1130 |
+
out["runtime_note"] = backend_note
|
| 1131 |
return out
|
| 1132 |
|
| 1133 |
+
configured = _api_key_wired(env_var)
|
| 1134 |
+
out["api_key_wired"] = configured
|
| 1135 |
+
out["credential_configured"] = configured
|
| 1136 |
+
out["configured"] = configured
|
| 1137 |
+
out["authenticated"] = False
|
| 1138 |
+
out["reachable"] = False
|
| 1139 |
+
out["model_ready"] = False
|
| 1140 |
+
out["inference_receipted"] = False
|
| 1141 |
+
out["operational"] = False
|
| 1142 |
+
out["state"] = (_STATE_CONFIGURED_UNVERIFIED if configured
|
| 1143 |
+
else _STATE_OFFLINE_UNTIL_KEYED)
|
| 1144 |
+
out["wired"] = False
|
| 1145 |
out["provider"] = m.get("provider")
|
| 1146 |
out["env_used"] = env_var or None
|
| 1147 |
+
out["env_present"] = configured
|
| 1148 |
out["base_url"] = m.get("api_base") or m.get("base_url")
|
| 1149 |
out["is_local"] = bool(m.get("open_weight"))
|
| 1150 |
+
out["honest_stub"] = True
|
| 1151 |
+
out["label"] = out["state"]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1152 |
return out
|
| 1153 |
|
| 1154 |
def _seed_forum() -> None:
|
|
|
|
| 1156 |
_forum_append({
|
| 1157 |
"ts": _now(), "source": "a11oy", "event": "registry_boot",
|
| 1158 |
"model_count": len(MODEL_REGISTRY), "doctrine": DOCTRINE,
|
| 1159 |
+
"note": ("a11oy canonical base registry initialised with %d records; "
|
| 1160 |
+
"runtime extensions are counted at request time"
|
| 1161 |
+
% len(MODEL_REGISTRY)),
|
| 1162 |
})
|
| 1163 |
_forum_append({
|
| 1164 |
"ts": _now(), "source": "operator", "event": "forum_join",
|
|
|
|
| 1189 |
do_probe = bool(probe)
|
| 1190 |
models = [_enrich_model(m, probe_local=do_probe) for m in MODEL_REGISTRY]
|
| 1191 |
wired = [m for m in models if m.get("wired")]
|
| 1192 |
+
configured = [m for m in models if m.get("configured")]
|
| 1193 |
+
reachable = [m for m in models if m.get("reachable")]
|
| 1194 |
+
receipted = [m for m in models if m.get("inference_receipted")]
|
| 1195 |
badges = [{
|
| 1196 |
"model_id": m["model_id"],
|
| 1197 |
"wired": bool(m.get("wired")),
|
| 1198 |
+
"configured": bool(m.get("configured")),
|
| 1199 |
+
"reachable": bool(m.get("reachable")),
|
| 1200 |
+
"inference_receipted": bool(m.get("inference_receipted")),
|
| 1201 |
+
"operational": bool(m.get("operational")),
|
| 1202 |
+
"state": m.get("state"),
|
| 1203 |
"provider": m.get("provider"),
|
| 1204 |
"env_used": m.get("env_used"),
|
| 1205 |
"base_url": m.get("base_url"),
|
| 1206 |
"honest_stub": bool(m.get("honest_stub", True)),
|
| 1207 |
"is_local": bool(m.get("is_local")),
|
| 1208 |
+
**({"label": m.get("label"),
|
| 1209 |
"own_metal": bool(m.get("own_metal"))} if m.get("own_metal") else {}),
|
| 1210 |
} for m in models]
|
| 1211 |
all_stub = (len(wired) == 0)
|
|
|
|
| 1215 |
_sov_badge = next((m for m in models if m.get("model_id") == _SOVEREIGN_BACKEND_ID), None)
|
| 1216 |
sovereign_snapshot = {
|
| 1217 |
"backend_id": _SOVEREIGN_BACKEND_ID,
|
| 1218 |
+
"canonical_model": _SOVEREIGN_MODEL_TAG,
|
| 1219 |
+
"requested_model": (_sov_badge.get("requested_model")
|
| 1220 |
+
if _sov_badge else _sovereign_model_slug() or None),
|
| 1221 |
+
"selected_model": (_sov_badge.get("selected_model")
|
| 1222 |
+
if _sov_badge else None),
|
| 1223 |
"provider": _SOVEREIGN_PROVENANCE,
|
| 1224 |
"url": _sovereign_base(),
|
| 1225 |
"env_present": _sovereign_env_present(),
|
|
|
|
| 1227 |
"reachable": (bool(_sov_badge.get("reachable")) if (do_probe and _sov_badge) else None),
|
| 1228 |
"label": (_sov_badge.get("label") if (do_probe and _sov_badge)
|
| 1229 |
else "UNPROBED (pass ?probe=1 for THIS-request reachability)"),
|
| 1230 |
+
"state": (_sov_badge.get("state") if (do_probe and _sov_badge)
|
| 1231 |
+
else "UNPROBED"),
|
| 1232 |
+
"inference_receipted": (bool(_sov_badge.get("inference_receipted"))
|
| 1233 |
+
if (do_probe and _sov_badge) else False),
|
| 1234 |
+
"operational": (bool(_sov_badge.get("operational"))
|
| 1235 |
+
if (do_probe and _sov_badge) else False),
|
| 1236 |
"route_order": "own-metal/sovereign FIRST (when reachable) → free → paid",
|
| 1237 |
"health_endpoint": "/api/a11oy/v1/llm/sovereign/health",
|
| 1238 |
}
|
|
|
|
| 1243 |
"model_count": len(models),
|
| 1244 |
"wired_count": len(wired),
|
| 1245 |
"wired_model_ids": [m["model_id"] for m in wired],
|
| 1246 |
+
"configured_count": len(configured),
|
| 1247 |
+
"reachable_count": len(reachable),
|
| 1248 |
+
"inference_receipted_count": len(receipted),
|
| 1249 |
+
"operational_count": len(wired),
|
| 1250 |
+
"registry_record_count": len(models),
|
| 1251 |
+
"unique_backend_count": len(models) - 1,
|
| 1252 |
+
"alias_groups": [{"backend_id": _SOVEREIGN_BACKEND_ID,
|
| 1253 |
+
"aliases": [_SOVEREIGN_LEGACY_ID],
|
| 1254 |
+
"record_count": 2, "backend_count": 1}],
|
| 1255 |
"models": models,
|
| 1256 |
"badges": badges,
|
| 1257 |
"tier_map": {
|
|
|
|
| 1269 |
"doctrine": DOCTRINE,
|
| 1270 |
"kernel_commit": _KERNEL,
|
| 1271 |
"honest_note": (
|
| 1272 |
+
("operational_count=0 — configuration and reachability are not "
|
| 1273 |
+
"inference proof. Providers remain offline or unreceipted until "
|
| 1274 |
+
"a successful durable inference receipt verifies.")
|
| 1275 |
if all_stub else
|
| 1276 |
+
("operational_count=%d — every operational provider has an exact "
|
| 1277 |
+
"served model and a verified durable inference receipt."
|
| 1278 |
% len(wired))),
|
| 1279 |
})
|
| 1280 |
|
|
|
|
| 1404 |
_want_sovereign = _explicit_sovereign or _offline_pref or _own_metal_first
|
| 1405 |
if _want_sovereign:
|
| 1406 |
gen = _mesh_gen
|
| 1407 |
+
_generated = bool(gen.get("live") and gen.get("text"))
|
| 1408 |
+
_generation_receipt = {"ok": False, "inference_receipted": False,
|
| 1409 |
+
"reason": "no successful generation to receipt"}
|
| 1410 |
+
if _generated:
|
| 1411 |
+
try:
|
| 1412 |
+
import szl_governed_infer as _gi
|
| 1413 |
+
_raw = gen.get("raw") or {}
|
| 1414 |
+
_tokens = (_raw.get("eval_count")
|
| 1415 |
+
or (_raw.get("usage") or {}).get("completion_tokens")
|
| 1416 |
+
or 0)
|
| 1417 |
+
_generation_receipt = _gi.record_provider_generation(
|
| 1418 |
+
prompt or _DEFAULT_SOVEREIGN_PROMPT,
|
| 1419 |
+
gen.get("text"), gen.get("model"), tokens=_tokens,
|
| 1420 |
+
base_url=gen.get("base_url") or "")
|
| 1421 |
+
except Exception as exc:
|
| 1422 |
+
_generation_receipt = {
|
| 1423 |
+
"ok": False, "inference_receipted": False,
|
| 1424 |
+
"reason": "durable receipt unavailable: %s" % type(exc).__name__}
|
| 1425 |
+
_state = _provider_state(
|
| 1426 |
+
configured=_sovereign_env_present(),
|
| 1427 |
+
reachable=_mesh_reachable,
|
| 1428 |
+
model_ready=bool(gen.get("model_ready")),
|
| 1429 |
+
inference_receipted=bool(
|
| 1430 |
+
_generation_receipt.get("inference_receipted")))
|
| 1431 |
# Prefer the first-class Wave-M backend id; fall back to legacy alias.
|
| 1432 |
sov_model = (_MODEL_BY_ID.get(_SOVEREIGN_BACKEND_ID)
|
| 1433 |
or _MODEL_BY_ID.get(_SOVEREIGN_LEGACY_ID)
|
| 1434 |
or MODEL_REGISTRY[0])
|
| 1435 |
sov_enriched = _enrich_model(sov_model)
|
| 1436 |
+
sov_enriched.update(_state)
|
| 1437 |
+
sov_enriched["wired"] = _state["operational"]
|
| 1438 |
+
sov_enriched["local_live"] = _mesh_reachable
|
| 1439 |
+
sov_enriched["generated"] = _generated
|
| 1440 |
+
sov_enriched["selected_model"] = gen.get("model")
|
| 1441 |
+
sov_enriched["model_resolution"] = gen.get("model_resolution")
|
| 1442 |
+
sov_enriched["generation_receipt"] = _generation_receipt
|
| 1443 |
+
sov_enriched["honest_stub"] = not _state["operational"]
|
| 1444 |
+
sov_enriched["label"] = _state["state"]
|
| 1445 |
if _explicit_sovereign:
|
| 1446 |
_why = "explicit request"
|
| 1447 |
elif _own_metal_first:
|
|
|
|
| 1449 |
else:
|
| 1450 |
_why = "offline preference, no cloud key wired"
|
| 1451 |
sov_reason = "%s selected (%s); " % (sov_model.get("model_id"), _why)
|
| 1452 |
+
if _generated and _state["operational"]:
|
| 1453 |
+
sov_reason += ("own-metal-first node %s (role=%s) generated real text "
|
| 1454 |
+
"and its durable inference receipt replay-verified."
|
| 1455 |
% (gen.get("base_url"), gen.get("role")))
|
| 1456 |
response_text = gen.get("text") or ""
|
| 1457 |
+
elif _generated:
|
| 1458 |
+
sov_reason += ("node generated real text, but durable inference receipt "
|
| 1459 |
+
"did not verify; provider remains unreceipted.")
|
| 1460 |
+
response_text = gen.get("text") or ""
|
| 1461 |
elif _mesh_reachable:
|
| 1462 |
sov_reason += ("node %s reachable but did not generate live — honest "
|
| 1463 |
"UNAVAILABLE (never fabricate)." % gen.get("base_url"))
|
|
|
|
| 1490 |
"model_display": sov_model.get("display_name"),
|
| 1491 |
"reason": sov_reason, "task_hint": task_hint,
|
| 1492 |
"own_metal_first": bool(_own_metal_first),
|
| 1493 |
+
"configured": _state["configured"],
|
| 1494 |
+
"reachable": _state["reachable"],
|
| 1495 |
+
"model_ready": _state["model_ready"],
|
| 1496 |
+
"generated": _generated,
|
| 1497 |
+
"inference_receipted": _state["inference_receipted"],
|
| 1498 |
+
"operational": _state["operational"],
|
| 1499 |
+
"state": _state["state"],
|
| 1500 |
+
"label": _state["state"],
|
| 1501 |
"api_key_wired": _sovereign_env_present(),
|
| 1502 |
+
"local_live": _mesh_reachable,
|
| 1503 |
"local_api_style": gen.get("api_style"),
|
| 1504 |
"local_base_url": gen.get("base_url"),
|
| 1505 |
"mesh_node_count": matrix.get("node_count", 0),
|
|
|
|
| 1507 |
"mesh_selected": matrix.get("selected"),
|
| 1508 |
"selected_role": gen.get("role"),
|
| 1509 |
"selected_base_url": gen.get("base_url"),
|
| 1510 |
+
"selected_model": gen.get("model"),
|
| 1511 |
+
"generation_receipt_hash": _generation_receipt.get("receipt_hash"),
|
| 1512 |
"doctrine": DOCTRINE, "kernel_commit": _KERNEL,
|
| 1513 |
"conjecture_note": "Λ = Conjecture 1 — NOT a theorem. CAUCHY_ND sorry open.",
|
| 1514 |
}
|
|
|
|
| 1518 |
"response": response_text,
|
| 1519 |
"model_selected": sov_enriched,
|
| 1520 |
"lambda_receipt": sov_receipt,
|
| 1521 |
+
"label": _state["state"],
|
| 1522 |
+
"reachable": _state["reachable"],
|
| 1523 |
+
"generated": _generated,
|
| 1524 |
+
"inference_receipted": _state["inference_receipted"],
|
| 1525 |
+
"operational": _state["operational"],
|
| 1526 |
+
"provider_state": _state,
|
| 1527 |
+
"generation_receipt": _generation_receipt,
|
| 1528 |
"routed_via": "%s via sovereign_mesh (%s)" % (
|
| 1529 |
sov_model.get("model_id"),
|
| 1530 |
+
gen.get("api_style") if _generated else "honest UNAVAILABLE"),
|
| 1531 |
"local": {k: gen.get(k) for k in
|
| 1532 |
+
("wired", "live", "generated", "api_style", "base_url", "role",
|
| 1533 |
+
"node_index", "model", "model_ready", "model_resolution",
|
| 1534 |
+
"note", "raw")
|
| 1535 |
if k in gen},
|
| 1536 |
"sovereign_mesh": matrix,
|
| 1537 |
"doctrine": DOCTRINE,
|
|
|
|
| 1577 |
except Exception:
|
| 1578 |
pass
|
| 1579 |
|
| 1580 |
+
provider_state = _provider_state(
|
| 1581 |
+
configured=bool(enriched.get("configured")),
|
| 1582 |
+
reachable=False,
|
| 1583 |
+
model_ready=False,
|
| 1584 |
+
inference_receipted=False,
|
| 1585 |
+
requires_key=True,
|
| 1586 |
+
)
|
| 1587 |
receipt = {
|
| 1588 |
"schema": "szl.llm_route.lambda_receipt/v1",
|
| 1589 |
"ts": _now(),
|
|
|
|
| 1599 |
"model_weight_sha256": mw_sha,
|
| 1600 |
"model_weight_method": mw_method,
|
| 1601 |
"api_key_wired": enriched["api_key_wired"],
|
| 1602 |
+
"configured": provider_state["configured"],
|
| 1603 |
+
"authenticated": False,
|
| 1604 |
+
"reachable": False,
|
| 1605 |
+
"model_ready": False,
|
| 1606 |
+
"inference_receipted": False,
|
| 1607 |
+
"operational": False,
|
| 1608 |
+
"provider_state": provider_state["state"],
|
| 1609 |
"doctrine": DOCTRINE,
|
| 1610 |
"kernel_commit": _KERNEL,
|
| 1611 |
"conjecture_note": "Λ = Conjecture 1 — NOT a theorem. CAUCHY_ND sorry open.",
|
|
|
|
| 1614 |
# Emit honest response (stub when no key)
|
| 1615 |
if enriched["api_key_wired"]:
|
| 1616 |
# Real call would go here — key present but routing call not implemented
|
| 1617 |
+
response_text = (
|
| 1618 |
+
f"[CONFIGURED_UNVERIFIED] A credential is present for "
|
| 1619 |
+
f"{selected_model['display_name']}, but this route did not perform "
|
| 1620 |
+
"an authenticated inference call. No model output is fabricated."
|
| 1621 |
+
)
|
| 1622 |
else:
|
| 1623 |
response_text = (
|
| 1624 |
f"[HONEST STUB] Would route to {selected_model['display_name']} "
|
|
|
|
| 1767 |
base = _sovereign_base()
|
| 1768 |
primary_probe = sovereign_probe(base)
|
| 1769 |
env_present = bool(primary_probe.get("env_present"))
|
|
|
|
| 1770 |
any_reachable = bool(matrix.get("any_reachable"))
|
| 1771 |
# Primary-node reachability (Wave-M compact contract mirrors the primary).
|
| 1772 |
reachable = bool(primary_probe.get("live"))
|
| 1773 |
+
resolution = _reconcile_sovereign_model(
|
| 1774 |
+
primary_probe.get("models", []), requested=_sovereign_model_slug())
|
| 1775 |
+
selected_model = resolution.get("selected_model")
|
| 1776 |
+
receipt_state = (_inference_receipt_state(selected_model)
|
| 1777 |
+
if selected_model else
|
| 1778 |
+
{"inference_receipted": False,
|
| 1779 |
+
"successful_receipt_count": 0,
|
| 1780 |
+
"total_receipt_count": 0,
|
| 1781 |
+
"chain_ok": True,
|
| 1782 |
+
"latest_receipt_hash": None})
|
| 1783 |
+
state = _provider_state(
|
| 1784 |
+
configured=env_present,
|
| 1785 |
+
reachable=reachable,
|
| 1786 |
+
model_ready=bool(resolution.get("model_ready")),
|
| 1787 |
+
inference_receipted=bool(receipt_state.get("inference_receipted")))
|
| 1788 |
+
label = state["state"]
|
| 1789 |
+
sovereign_status = (_STATE_LIVE_RECEIPTED
|
| 1790 |
+
if state["operational"] else
|
| 1791 |
+
(_STATE_REACHABLE_UNRECEIPTED
|
| 1792 |
+
if any_reachable else _STATE_UNAVAILABLE))
|
| 1793 |
return JSONResponse({
|
| 1794 |
# ── Wave-M required compact contract ──
|
| 1795 |
# `model` = canonical sovereign model tag; `configured_model` (below)
|
| 1796 |
# is the runtime-overridable ollama tag the node is asked to serve.
|
| 1797 |
"reachable": reachable,
|
| 1798 |
+
"model": selected_model,
|
| 1799 |
"url": base,
|
| 1800 |
"provider": _SOVEREIGN_PROVENANCE,
|
| 1801 |
"label": label,
|
|
|
|
| 1806 |
"model_id": _SOVEREIGN_BACKEND_ID,
|
| 1807 |
"legacy_alias": _SOVEREIGN_LEGACY_ID,
|
| 1808 |
"model_slug": _SOVEREIGN_MODEL_TAG,
|
| 1809 |
+
"canonical_model": _SOVEREIGN_MODEL_TAG,
|
| 1810 |
+
"requested_model": resolution.get("requested_model"),
|
| 1811 |
+
"selected_model": selected_model,
|
| 1812 |
+
"model_ready": state["model_ready"],
|
| 1813 |
+
"model_resolution": resolution,
|
| 1814 |
+
"configured": state["configured"],
|
| 1815 |
+
"inference_receipted": state["inference_receipted"],
|
| 1816 |
+
"operational": state["operational"],
|
| 1817 |
+
"state": state["state"],
|
| 1818 |
+
"receipt_state": receipt_state,
|
| 1819 |
# ── Mesh (multi-node) reachability matrix (Wave N, Dev 3) ──
|
| 1820 |
"sovereign_status": sovereign_status, # honest label: LIVE | UNAVAILABLE (mesh-wide)
|
| 1821 |
"mesh": matrix,
|
|
|
|
| 1825 |
"selected_node": matrix.get("selected"),
|
| 1826 |
"own_metal_first": True,
|
| 1827 |
"fallthrough_to_cloud": (not any_reachable),
|
| 1828 |
+
"env_vars": {
|
| 1829 |
+
"primary": _SOVEREIGN_ENV,
|
| 1830 |
+
"code_primary": list(_CODE_SOVEREIGN_ENVS),
|
| 1831 |
+
"gateway": _GATEWAY_ENV,
|
| 1832 |
+
"nodes": _SOVEREIGN_NODES_ENV,
|
| 1833 |
+
},
|
| 1834 |
+
"env_used": _sovereign_env_used(),
|
| 1835 |
# ── Backward-compatible single-node (primary) fields ──
|
| 1836 |
"env_var": _SOVEREIGN_ENV,
|
| 1837 |
"env_present": env_present,
|
| 1838 |
+
"wired": state["operational"],
|
| 1839 |
"live": reachable, # primary-node THIS-request liveness (== reachable)
|
| 1840 |
+
"honest_stub": not state["operational"],
|
| 1841 |
"base_url": base,
|
| 1842 |
"api_style": primary_probe.get("api_style"),
|
| 1843 |
"served_models": primary_probe.get("models", []),
|
| 1844 |
+
"configured_model": _sovereign_model_slug() or None,
|
| 1845 |
"probed": primary_probe.get("probed", []),
|
| 1846 |
"probe_ua": "browser-UA (Cloudflare-front safe)",
|
| 1847 |
"note": matrix.get("note", ""),
|
|
|
|
| 1868 |
"provider": provider,
|
| 1869 |
"env_var": env_var, # NAME ONLY — never the secret value
|
| 1870 |
"key_present": present,
|
| 1871 |
+
"configured": present,
|
| 1872 |
+
"authenticated": False,
|
| 1873 |
+
"reachable": False,
|
| 1874 |
+
"model_ready": False,
|
| 1875 |
+
"inference_receipted": False,
|
| 1876 |
+
"operational": False,
|
| 1877 |
+
"state": (_STATE_CONFIGURED_UNVERIFIED if present
|
| 1878 |
+
else _STATE_OFFLINE_UNTIL_KEYED),
|
| 1879 |
})
|
| 1880 |
if present:
|
| 1881 |
seen_present.add(provider)
|
|
|
|
| 1899 |
_matrix = sovereign_mesh_matrix()
|
| 1900 |
_any = bool(_matrix.get("any_reachable"))
|
| 1901 |
_sel = _matrix.get("selected") or {}
|
| 1902 |
+
_resolution = _reconcile_sovereign_model(
|
| 1903 |
+
_sel.get("served_models", []), requested=_sovereign_model_slug())
|
| 1904 |
+
_selected_model = _resolution.get("selected_model")
|
| 1905 |
+
_receipt = (_inference_receipt_state(_selected_model)
|
| 1906 |
+
if _selected_model else
|
| 1907 |
+
{"inference_receipted": False,
|
| 1908 |
+
"successful_receipt_count": 0,
|
| 1909 |
+
"total_receipt_count": 0,
|
| 1910 |
+
"chain_ok": True,
|
| 1911 |
+
"latest_receipt_hash": None})
|
| 1912 |
+
_local_state = _provider_state(
|
| 1913 |
+
configured=_sovereign_env_present(),
|
| 1914 |
+
reachable=_any,
|
| 1915 |
+
model_ready=bool(_resolution.get("model_ready")),
|
| 1916 |
+
inference_receipted=bool(_receipt.get("inference_receipted")))
|
| 1917 |
_mesh_summary = {
|
| 1918 |
"node_count": _matrix.get("node_count", 0),
|
| 1919 |
"reachable_count": _matrix.get("reachable_count", 0),
|
|
|
|
| 1930 |
"nodes_env": _SOVEREIGN_NODES_ENV,
|
| 1931 |
"env_present": _sovereign_env_present(),
|
| 1932 |
"live": _any, "reachable": _any,
|
| 1933 |
+
"configured": _local_state["configured"],
|
| 1934 |
+
"model_ready": _local_state["model_ready"],
|
| 1935 |
+
"requested_model": _resolution.get("requested_model"),
|
| 1936 |
+
"selected_model": _selected_model,
|
| 1937 |
+
"model_resolution": _resolution,
|
| 1938 |
+
"inference_receipted": _local_state["inference_receipted"],
|
| 1939 |
+
"operational": _local_state["operational"],
|
| 1940 |
+
"wired": _local_state["operational"],
|
| 1941 |
+
"state": _local_state["state"],
|
| 1942 |
+
"label": _local_state["state"],
|
| 1943 |
+
"receipt_state": _receipt,
|
| 1944 |
"served_models": _sel.get("served_models", []),
|
| 1945 |
"note": _matrix.get("note", ""),
|
| 1946 |
}
|
|
|
|
| 1950 |
"env_var": _SOVEREIGN_ENV, "base_url": base or None,
|
| 1951 |
"nodes_env": _SOVEREIGN_NODES_ENV,
|
| 1952 |
"env_present": _sovereign_env_present(), "live": None,
|
| 1953 |
+
"reachable": None, "configured": _sovereign_env_present(),
|
| 1954 |
+
"model_ready": False, "inference_receipted": False,
|
| 1955 |
+
"operational": False, "wired": False,
|
| 1956 |
+
"state": "UNPROBED", "label": "UNPROBED",
|
| 1957 |
"note": "pass ?probe=1 to ping the mesh for THIS-request liveness",
|
| 1958 |
}
|
| 1959 |
|
|
|
|
| 1964 |
"role": "router key/liveness status — provider NAMES only, never secrets",
|
| 1965 |
"providers": providers,
|
| 1966 |
"provider_keys_present": provider_keys_present,
|
| 1967 |
+
"provider_configured_count": len(provider_keys_present),
|
| 1968 |
+
"provider_operational_count": 0,
|
| 1969 |
+
"provider_wired_count": 0,
|
| 1970 |
"code_agent_credential": code_key_public,
|
| 1971 |
"local_nodes": [local_node],
|
| 1972 |
"sovereign_mesh": _mesh_summary,
|
| 1973 |
"any_cloud_key_present": len(provider_keys_present) > 0,
|
| 1974 |
"doctrine": DOCTRINE,
|
| 1975 |
"kernel_commit": _KERNEL,
|
| 1976 |
+
"honest_note": ("Presence is a real os.environ check THIS request, but "
|
| 1977 |
+
"configuration is not authentication, reachability, or "
|
| 1978 |
+
"receipted inference. Secret values are never returned."),
|
| 1979 |
})
|
| 1980 |
|
| 1981 |
return {
|
|
@@ -0,0 +1,363 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 3 |
+
"""Build the deterministic, fail-closed M1 corpus decision ledgers.
|
| 4 |
+
|
| 5 |
+
This module is an accounting and evaluation-readiness tool. It reads only
|
| 6 |
+
versioned local sources, performs no network calls, and never trains or promotes
|
| 7 |
+
a model. Every Brain graph node receives an explicit decision. External
|
| 8 |
+
metadata without an item-level license and person metadata are quarantined;
|
| 9 |
+
they are never silently converted into training text.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
from __future__ import annotations
|
| 13 |
+
|
| 14 |
+
import hashlib
|
| 15 |
+
import json
|
| 16 |
+
from collections import Counter
|
| 17 |
+
from pathlib import Path
|
| 18 |
+
from typing import Any, Iterable
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
ROOT = Path(__file__).resolve().parent
|
| 22 |
+
OUT_DIR = ROOT / "model_release" / "m1"
|
| 23 |
+
GRAPH_LEDGER = OUT_DIR / "brain-ingest-ledger.jsonl"
|
| 24 |
+
FORMULA_LEDGER = OUT_DIR / "formula-curriculum-ledger.jsonl"
|
| 25 |
+
CORPUS_MANIFEST = OUT_DIR / "corpus-ingestion-manifest.json"
|
| 26 |
+
EVALUATION_MANIFEST = OUT_DIR / "evaluation-manifest.json"
|
| 27 |
+
EXPECTED_RAW_NODES = 9464
|
| 28 |
+
EXPECTED_DISTINCT_ARTIFACTS = 4229
|
| 29 |
+
PERSON_KINDS = {"person", "author"}
|
| 30 |
+
LOCAL_LICENSED_KINDS = {"estate", "endpoint", "topic", "surface", "formula"}
|
| 31 |
+
FORMULA_STATUS_VOCABULARY = ["KERNEL_ACCEPTED", "CONDITIONAL", "OPEN", "REFUTED"]
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def _canonical(value: Any) -> bytes:
|
| 35 |
+
return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def _sha(value: bytes) -> str:
|
| 39 |
+
return hashlib.sha256(value).hexdigest()
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def _sha_file(path: Path) -> str:
|
| 43 |
+
digest = hashlib.sha256()
|
| 44 |
+
with path.open("rb") as stream:
|
| 45 |
+
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
|
| 46 |
+
digest.update(chunk)
|
| 47 |
+
return digest.hexdigest()
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def _receipt(prefix: str, value: Any) -> str:
|
| 51 |
+
return f"{prefix}:sha256:{_sha(_canonical(value))}"
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def _source_family(node: dict[str, Any]) -> str:
|
| 55 |
+
kind = str(node.get("kind") or "unknown").lower()
|
| 56 |
+
source = str(node.get("source") or "").lower()
|
| 57 |
+
if kind in PERSON_KINDS:
|
| 58 |
+
return "authorship-person-metadata"
|
| 59 |
+
if kind == "formula":
|
| 60 |
+
# The raw graph row is an index duplicate, not the canonical formula
|
| 61 |
+
# curriculum record. Keep it in its own family so the raw inventory
|
| 62 |
+
# can remain quarantined while the canonical record stays HOLDOUT.
|
| 63 |
+
return "brain-raw-formula-index"
|
| 64 |
+
if kind in {"estate", "endpoint", "topic", "surface"} and int(node.get("layer", -1)) >= 0:
|
| 65 |
+
return "a11oy-versioned-runtime"
|
| 66 |
+
if kind == "repo" or "github" in source or "gitlab" in source:
|
| 67 |
+
return "repository-metadata"
|
| 68 |
+
if kind == "paper" or "arxiv" in source:
|
| 69 |
+
return "academic-publication-metadata"
|
| 70 |
+
if kind in {"dataset", "benchmark"}:
|
| 71 |
+
return "dataset-benchmark-metadata"
|
| 72 |
+
if kind in {"standard", "org", "lab", "axis"}:
|
| 73 |
+
return "research-landscape-metadata"
|
| 74 |
+
return "other-graph-metadata"
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def _split_for_family(family: str) -> str:
|
| 78 |
+
# Raw Brain rows are inventory, never training data. Admitted canonical
|
| 79 |
+
# rows are built by the separate evidence/formula generators.
|
| 80 |
+
return "QUARANTINE"
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def _formula_status(formula_id: str, meta: dict[str, Any]) -> str:
|
| 84 |
+
locked = {"F1", "F4", "F7", "F11", "F12", "F18", "F19", "F22"}
|
| 85 |
+
if formula_id in locked and str(meta.get("proof_status")) == "PROVED" and str(meta.get("lean_status")) == "PROVED":
|
| 86 |
+
return "KERNEL_ACCEPTED"
|
| 87 |
+
evidence = " ".join(str(meta.get(key) or "") for key in ("proof_status", "lean_status", "maturity", "status")).upper()
|
| 88 |
+
if "REFUT" in evidence:
|
| 89 |
+
return "REFUTED"
|
| 90 |
+
if "CONDITIONAL" in evidence or "AXIOM-GATED" in evidence:
|
| 91 |
+
return "CONDITIONAL"
|
| 92 |
+
return "OPEN"
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def _formula_canonical_text(formula_id: str, meta: dict[str, Any], status: str) -> str:
|
| 96 |
+
text_parts = [f"formula_id: {formula_id}", f"formula_status: {status}"]
|
| 97 |
+
for field in ("name", "primitive", "identity_doc", "latex", "context", "source_file", "source_line"):
|
| 98 |
+
if meta.get(field) not in (None, ""):
|
| 99 |
+
text_parts.append(f"{field}: {meta[field]}")
|
| 100 |
+
return "\n".join(text_parts)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def _formula_receipt_id(family: str, formula_id: str, meta: dict[str, Any]) -> tuple[str, str, str]:
|
| 104 |
+
status = _formula_status(formula_id, meta)
|
| 105 |
+
canonical_text = _formula_canonical_text(formula_id, meta, status)
|
| 106 |
+
text_sha = _sha(canonical_text.encode("utf-8"))
|
| 107 |
+
stable = {"source_family": family, "formula_id": formula_id,
|
| 108 |
+
"formula_status": status, "canonical_text_sha256": text_sha}
|
| 109 |
+
return _receipt("formula", stable), canonical_text, status
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
def _node_canonical_text(node: dict[str, Any]) -> str:
|
| 113 |
+
fields = [
|
| 114 |
+
f"title: {str(node.get('title') or '').strip()}",
|
| 115 |
+
f"kind: {str(node.get('kind') or 'unknown')}",
|
| 116 |
+
f"evidence_label: {str(node.get('label') or 'UNKNOWN')}",
|
| 117 |
+
]
|
| 118 |
+
for key in ("axis", "organ", "primitive", "source", "url", "path", "note"):
|
| 119 |
+
value = node.get(key)
|
| 120 |
+
if value not in (None, ""):
|
| 121 |
+
fields.append(f"{key}: {str(value).strip()}")
|
| 122 |
+
return "\n".join(fields)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def _graph_formula_receipts(nodes: Iterable[dict[str, Any]]) -> dict[str, str]:
|
| 126 |
+
result: dict[str, str] = {}
|
| 127 |
+
for node in nodes:
|
| 128 |
+
if node.get("kind") == "formula" and node.get("formula_id"):
|
| 129 |
+
stable = {key: value for key, value in node.items() if key not in {"degree"}}
|
| 130 |
+
result[str(node["formula_id"])] = _receipt("brain-node", stable)
|
| 131 |
+
return result
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _build_node_rows(nodes: list[dict[str, Any]], evaluation_receipt_id: str,
|
| 135 |
+
formula_receipts: dict[str, str]) -> list[dict[str, Any]]:
|
| 136 |
+
from szl_puriq_formulas import FORMULA_META
|
| 137 |
+
|
| 138 |
+
rows: list[dict[str, Any]] = []
|
| 139 |
+
seen_ids: set[str] = set()
|
| 140 |
+
for node in sorted(nodes, key=lambda item: str(item.get("id") or "")):
|
| 141 |
+
node_id = str(node.get("id") or "")
|
| 142 |
+
if not node_id or node_id in seen_ids:
|
| 143 |
+
raise ValueError(f"Brain node id is absent or duplicated: {node_id!r}")
|
| 144 |
+
seen_ids.add(node_id)
|
| 145 |
+
stable = {key: value for key, value in node.items() if key not in {"degree"}}
|
| 146 |
+
receipt_id = _receipt("brain-node", stable)
|
| 147 |
+
family = _source_family(node)
|
| 148 |
+
split = _split_for_family(family)
|
| 149 |
+
kind = str(node.get("kind") or "unknown").lower()
|
| 150 |
+
is_person = kind in PERSON_KINDS
|
| 151 |
+
locally_licensed = int(node.get("layer", -1)) >= 0 and kind in LOCAL_LICENSED_KINDS
|
| 152 |
+
formula_id = str(node.get("formula_id") or "") if kind == "formula" else ""
|
| 153 |
+
formula_status = _formula_status(formula_id, FORMULA_META.get(formula_id, {})) if formula_id else None
|
| 154 |
+
if is_person:
|
| 155 |
+
safety = "QUARANTINE_PERSON_METADATA"
|
| 156 |
+
elif kind == "formula":
|
| 157 |
+
safety = "QUARANTINE_RAW_GRAPH_DUPLICATE_FORMULA"
|
| 158 |
+
elif not locally_licensed:
|
| 159 |
+
safety = "QUARANTINE_LICENSE_UNKNOWN"
|
| 160 |
+
else:
|
| 161 |
+
safety = "QUARANTINE_RAW_GRAPH_NOT_ADMITTED"
|
| 162 |
+
decision = "QUARANTINE"
|
| 163 |
+
canonical_text = _node_canonical_text(node)
|
| 164 |
+
capture = node.get("captured_at") or node.get("harvested_at")
|
| 165 |
+
freshness = "CAPTURED_SOURCE_DATE" if capture else (
|
| 166 |
+
"VERSION_BOUND_NOT_TIME_FRESH" if locally_licensed else "UNKNOWN_NO_SOURCE_TIMESTAMP"
|
| 167 |
+
)
|
| 168 |
+
rows.append({
|
| 169 |
+
"schema": "szl.m1-brain-ingest-decision/v1",
|
| 170 |
+
"receipt_id": receipt_id,
|
| 171 |
+
"brain_anatomy_receipt_id": receipt_id,
|
| 172 |
+
"node_id": node_id,
|
| 173 |
+
"canonical_artifact_id": node_id if not is_person else None,
|
| 174 |
+
"artifact_role": "ATTRIBUTION_METADATA" if is_person else "DISTINCT_ARTIFACT",
|
| 175 |
+
"kind": kind,
|
| 176 |
+
"source_family": family,
|
| 177 |
+
"source_family_split": split,
|
| 178 |
+
"provenance": {
|
| 179 |
+
"source": node.get("source") or node.get("derived_from") or "versioned-local-graph",
|
| 180 |
+
"url": node.get("url"),
|
| 181 |
+
"captured_at": capture,
|
| 182 |
+
"evidence_label": node.get("label") or "UNKNOWN",
|
| 183 |
+
"graph_node_receipt_id": receipt_id,
|
| 184 |
+
},
|
| 185 |
+
"license": {
|
| 186 |
+
"spdx": "Apache-2.0" if locally_licensed else None,
|
| 187 |
+
"state": "VERSIONED_REPOSITORY_LICENSE" if locally_licensed else "UNKNOWN_ITEM_LEVEL_LICENSE",
|
| 188 |
+
"evidence": "LICENSE" if locally_licensed else None,
|
| 189 |
+
},
|
| 190 |
+
"freshness": {"state": freshness, "captured_at": capture},
|
| 191 |
+
"safety_decision": safety,
|
| 192 |
+
"training_decision": decision,
|
| 193 |
+
"training_eligible": False,
|
| 194 |
+
"formula_id": formula_id or None,
|
| 195 |
+
"formula_status": formula_status,
|
| 196 |
+
"formula_receipt_id": formula_receipts.get(formula_id) if formula_id else None,
|
| 197 |
+
"evaluation_receipt_id": evaluation_receipt_id,
|
| 198 |
+
"canonical_text": canonical_text,
|
| 199 |
+
"canonical_text_sha256": _sha(canonical_text.encode("utf-8")),
|
| 200 |
+
})
|
| 201 |
+
return rows
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def _build_formula_rows(nodes: list[dict[str, Any]], evaluation_receipt_id: str) -> list[dict[str, Any]]:
|
| 205 |
+
from szl_puriq_formulas import FORMULA_META
|
| 206 |
+
|
| 207 |
+
graph_receipts = _graph_formula_receipts(nodes)
|
| 208 |
+
rows: list[dict[str, Any]] = []
|
| 209 |
+
sources: list[tuple[str, str, dict[str, Any]]] = [
|
| 210 |
+
("canonical-formula-registry", formula_id, dict(meta))
|
| 211 |
+
for formula_id, meta in FORMULA_META.items()
|
| 212 |
+
]
|
| 213 |
+
knowledge = json.loads((ROOT / "knowledge.json").read_text(encoding="utf-8"))
|
| 214 |
+
for item in knowledge.get("formulas") or []:
|
| 215 |
+
if isinstance(item, dict) and item.get("id"):
|
| 216 |
+
sources.append(("thesis-formula-corpus", str(item["id"]), dict(item)))
|
| 217 |
+
|
| 218 |
+
seen: set[tuple[str, str]] = set()
|
| 219 |
+
for family, formula_id, meta in sorted(sources, key=lambda item: (item[0], item[1])):
|
| 220 |
+
key = (family, formula_id)
|
| 221 |
+
if key in seen:
|
| 222 |
+
raise ValueError(f"formula source duplicate: {key}")
|
| 223 |
+
seen.add(key)
|
| 224 |
+
receipt_id, canonical_text, status = _formula_receipt_id(family, formula_id, meta)
|
| 225 |
+
if status == "KERNEL_ACCEPTED":
|
| 226 |
+
role = "HOLDOUT_POSITIVE"
|
| 227 |
+
elif status == "REFUTED":
|
| 228 |
+
role = "HOLDOUT_NEGATIVE"
|
| 229 |
+
else:
|
| 230 |
+
role = "HOLDOUT_ABSTENTION"
|
| 231 |
+
rows.append({
|
| 232 |
+
"schema": "szl.m1-formula-curriculum-decision/v1",
|
| 233 |
+
"receipt_id": receipt_id,
|
| 234 |
+
"formula_receipt_id": receipt_id,
|
| 235 |
+
"brain_anatomy_receipt_id": graph_receipts.get(formula_id),
|
| 236 |
+
"formula_id": formula_id,
|
| 237 |
+
"source_family": family,
|
| 238 |
+
"source_family_split": "HOLDOUT",
|
| 239 |
+
"formula_status": status,
|
| 240 |
+
"training_decision": role,
|
| 241 |
+
"abstention_required": status in {"OPEN", "CONDITIONAL"},
|
| 242 |
+
"negative_example": status == "REFUTED",
|
| 243 |
+
"provenance": {
|
| 244 |
+
"source": "szl_puriq_formulas.FORMULA_META" if family == "canonical-formula-registry" else "knowledge.json#/formulas",
|
| 245 |
+
"source_file": meta.get("source_file"),
|
| 246 |
+
"source_line": meta.get("source_line"),
|
| 247 |
+
},
|
| 248 |
+
"license": {"spdx": "Apache-2.0", "state": "VERSIONED_REPOSITORY_LICENSE", "evidence": "LICENSE"},
|
| 249 |
+
"freshness": {"state": "VERSION_BOUND_NOT_TIME_FRESH", "captured_at": None},
|
| 250 |
+
"safety_decision": "ALLOW_HOLDOUT_ONLY",
|
| 251 |
+
"evaluation_receipt_id": evaluation_receipt_id,
|
| 252 |
+
"canonical_text": canonical_text,
|
| 253 |
+
"canonical_text_sha256": _sha(canonical_text.encode("utf-8")),
|
| 254 |
+
})
|
| 255 |
+
return rows
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
def _write_jsonl(path: Path, rows: Iterable[dict[str, Any]]) -> None:
|
| 259 |
+
with path.open("w", encoding="utf-8", newline="\n") as stream:
|
| 260 |
+
for row in rows:
|
| 261 |
+
stream.write(json.dumps(row, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n")
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def build() -> dict[str, Any]:
|
| 265 |
+
from a11oy_brain_graph import get_brain_graph
|
| 266 |
+
|
| 267 |
+
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
| 268 |
+
graph = get_brain_graph(refresh=True)
|
| 269 |
+
nodes = list(graph.get("nodes") or [])
|
| 270 |
+
if len(nodes) != EXPECTED_RAW_NODES:
|
| 271 |
+
raise ValueError(f"expected {EXPECTED_RAW_NODES} Brain nodes, observed {len(nodes)}")
|
| 272 |
+
distinct = sum(1 for node in nodes if str(node.get("kind") or "").lower() not in PERSON_KINDS)
|
| 273 |
+
if distinct != EXPECTED_DISTINCT_ARTIFACTS:
|
| 274 |
+
raise ValueError(f"expected {EXPECTED_DISTINCT_ARTIFACTS} distinct artifacts, observed {distinct}")
|
| 275 |
+
|
| 276 |
+
evaluation_sha = _sha_file(EVALUATION_MANIFEST)
|
| 277 |
+
evaluation_receipt_id = f"m1-evaluation:sha256:{evaluation_sha}"
|
| 278 |
+
from szl_puriq_formulas import FORMULA_META
|
| 279 |
+
formula_receipts = {
|
| 280 |
+
formula_id: _formula_receipt_id("canonical-formula-registry", formula_id, dict(meta))[0]
|
| 281 |
+
for formula_id, meta in FORMULA_META.items()
|
| 282 |
+
}
|
| 283 |
+
node_rows = _build_node_rows(nodes, evaluation_receipt_id, formula_receipts)
|
| 284 |
+
formula_rows = _build_formula_rows(nodes, evaluation_receipt_id)
|
| 285 |
+
_write_jsonl(GRAPH_LEDGER, node_rows)
|
| 286 |
+
_write_jsonl(FORMULA_LEDGER, formula_rows)
|
| 287 |
+
|
| 288 |
+
node_decisions = Counter(row["training_decision"] for row in node_rows)
|
| 289 |
+
node_safety = Counter(row["safety_decision"] for row in node_rows)
|
| 290 |
+
formula_status = Counter(row["formula_status"] for row in formula_rows)
|
| 291 |
+
formula_roles = Counter(row["training_decision"] for row in formula_rows)
|
| 292 |
+
source_families: dict[str, dict[str, Any]] = {}
|
| 293 |
+
for row in [*node_rows, *formula_rows]:
|
| 294 |
+
family = row["source_family"]
|
| 295 |
+
entry = source_families.setdefault(family, {"split": row["source_family_split"], "rows": 0})
|
| 296 |
+
if entry["split"] != row["source_family_split"]:
|
| 297 |
+
raise ValueError(f"source family leakage across splits: {family}")
|
| 298 |
+
entry["rows"] += 1
|
| 299 |
+
|
| 300 |
+
stable_nodes = [{key: value for key, value in node.items() if key != "degree"}
|
| 301 |
+
for node in sorted(nodes, key=lambda item: str(item.get("id") or ""))]
|
| 302 |
+
graph_snapshot_sha = _sha(_canonical(stable_nodes))
|
| 303 |
+
manifest = {
|
| 304 |
+
"schema": "szl.m1-corpus-ingestion-manifest/v1",
|
| 305 |
+
"candidate_id": "a11oy-evidence-1.5b-sft-lora",
|
| 306 |
+
"release_state": "NOT_PROMOTED",
|
| 307 |
+
"training_state": "NOT_RUN",
|
| 308 |
+
"training_relation": "PROPOSAL_ONLY_NOT_USED_BY_EXISTING_ADAPTER",
|
| 309 |
+
"quality_claim": "NOT_ESTABLISHED",
|
| 310 |
+
"source_snapshot": {
|
| 311 |
+
"brain_graph_receipt_id": f"brain-graph:sha256:{graph_snapshot_sha}",
|
| 312 |
+
"brain_graph_sha256": graph_snapshot_sha,
|
| 313 |
+
"raw_node_count": len(node_rows),
|
| 314 |
+
"distinct_artifact_count": distinct,
|
| 315 |
+
"person_metadata_count": len(node_rows) - distinct,
|
| 316 |
+
"link_count_reported_by_graph": graph.get("link_count"),
|
| 317 |
+
"versioned_sources_only": True,
|
| 318 |
+
"network_fetches": 0,
|
| 319 |
+
},
|
| 320 |
+
"ledgers": {
|
| 321 |
+
"brain_nodes": {"path": GRAPH_LEDGER.name, "rows": len(node_rows), "bytes": GRAPH_LEDGER.stat().st_size,
|
| 322 |
+
"sha256": _sha_file(GRAPH_LEDGER), "schema": "szl.m1-brain-ingest-decision/v1"},
|
| 323 |
+
"formulas": {"path": FORMULA_LEDGER.name, "rows": len(formula_rows), "bytes": FORMULA_LEDGER.stat().st_size,
|
| 324 |
+
"sha256": _sha_file(FORMULA_LEDGER), "schema": "szl.m1-formula-curriculum-decision/v1"},
|
| 325 |
+
},
|
| 326 |
+
"coverage": {
|
| 327 |
+
"node_decisions_total": len(node_rows),
|
| 328 |
+
"node_decisions_expected": EXPECTED_RAW_NODES,
|
| 329 |
+
"node_decision_coverage": 1.0,
|
| 330 |
+
"distinct_artifacts": distinct,
|
| 331 |
+
"person_metadata": len(node_rows) - distinct,
|
| 332 |
+
"node_decisions": dict(sorted(node_decisions.items())),
|
| 333 |
+
"node_safety": dict(sorted(node_safety.items())),
|
| 334 |
+
"raw_nodes_training_quarantined": sum(not bool(row["training_eligible"]) for row in node_rows),
|
| 335 |
+
"training_eligible_nodes": sum(bool(row["training_eligible"]) for row in node_rows),
|
| 336 |
+
"formula_records_current_versioned_sources": len(formula_rows),
|
| 337 |
+
"formula_requested_200_claim": "NOT_VERIFIED_BY_CURRENT_VERSIONED_SOURCES",
|
| 338 |
+
"formula_status_vocabulary": FORMULA_STATUS_VOCABULARY,
|
| 339 |
+
"formula_status": {status: formula_status.get(status, 0) for status in FORMULA_STATUS_VOCABULARY},
|
| 340 |
+
"formula_roles": dict(sorted(formula_roles.items())),
|
| 341 |
+
"abstention_examples": sum(bool(row["abstention_required"]) for row in formula_rows),
|
| 342 |
+
"negative_examples": sum(bool(row["negative_example"]) for row in formula_rows),
|
| 343 |
+
"quarantined_or_excluded_nodes": sum(not bool(row["training_eligible"]) for row in node_rows),
|
| 344 |
+
"missing_item_level_license_nodes": sum(row["license"]["state"] == "UNKNOWN_ITEM_LEVEL_LICENSE" for row in node_rows),
|
| 345 |
+
"missing_source_timestamp_nodes": sum(row["freshness"]["state"] == "UNKNOWN_NO_SOURCE_TIMESTAMP" for row in node_rows),
|
| 346 |
+
},
|
| 347 |
+
"source_family_split": dict(sorted(source_families.items())),
|
| 348 |
+
"leakage_policy": "all rows from one source_family have exactly one split; formula families are HOLDOUT; quarantined rows are never training text",
|
| 349 |
+
"resulting_evaluation_receipt": {
|
| 350 |
+
"receipt_id": evaluation_receipt_id,
|
| 351 |
+
"path": EVALUATION_MANIFEST.name,
|
| 352 |
+
"bytes": EVALUATION_MANIFEST.stat().st_size,
|
| 353 |
+
"sha256": evaluation_sha,
|
| 354 |
+
"state": "INCOMPLETE",
|
| 355 |
+
"promotion_decision": "NOT_PROMOTED",
|
| 356 |
+
},
|
| 357 |
+
}
|
| 358 |
+
CORPUS_MANIFEST.write_text(json.dumps(manifest, indent=2, ensure_ascii=False, sort_keys=True) + "\n", encoding="utf-8", newline="\n")
|
| 359 |
+
return manifest
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
if __name__ == "__main__":
|
| 363 |
+
print(json.dumps(build(), indent=2, ensure_ascii=True, sort_keys=True))
|
|
@@ -0,0 +1,833 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 3 |
+
"""Fail-closed operational gate for the M1 experimental PEFT candidate.
|
| 4 |
+
|
| 5 |
+
This module does not ship model weights, download artifacts, train, publish, or
|
| 6 |
+
call a remote provider. It will run bounded inference only when every local
|
| 7 |
+
artifact and evidence receipt matches the immutable manifest, the local runtime
|
| 8 |
+
and GPU pass admission, and the operator binds the exact in-process provider
|
| 9 |
+
identity. ``NOT_PROMOTED`` is always preserved and production use is rejected.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
from __future__ import annotations
|
| 13 |
+
|
| 14 |
+
import asyncio
|
| 15 |
+
import gc
|
| 16 |
+
import hashlib
|
| 17 |
+
import importlib.util
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
import shutil
|
| 21 |
+
import subprocess
|
| 22 |
+
import threading
|
| 23 |
+
import time
|
| 24 |
+
from collections import Counter
|
| 25 |
+
from datetime import datetime, timezone
|
| 26 |
+
from pathlib import Path
|
| 27 |
+
from typing import Any
|
| 28 |
+
|
| 29 |
+
from fastapi import Request
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
SCHEMA = "szl.m1-operational-gate/v1"
|
| 33 |
+
INFER_SCHEMA = "szl.m1-experimental-inference-request/v1"
|
| 34 |
+
RECEIPT_SCHEMA = "szl.m1-experimental-inference-receipt/v1"
|
| 35 |
+
READY = "READY_EXPERIMENTAL"
|
| 36 |
+
BLOCKED = "BLOCKED"
|
| 37 |
+
UNAVAILABLE = "UNAVAILABLE"
|
| 38 |
+
PASS = "PASS"
|
| 39 |
+
MANIFEST_DIR = Path(__file__).resolve().parent / "model_release" / "m1"
|
| 40 |
+
MANIFEST_PATH = MANIFEST_DIR / "operational-manifest.json"
|
| 41 |
+
PAGE_PATH = Path(__file__).resolve().parent / "web" / "m1-model.html"
|
| 42 |
+
_INFERENCE_LOCK = threading.Lock()
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class ContractError(ValueError):
|
| 46 |
+
"""The caller supplied a request outside the fixed experimental contract."""
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def _now() -> str:
|
| 50 |
+
return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def _canonical(value: Any) -> bytes:
|
| 54 |
+
return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def _digest_bytes(value: bytes) -> str:
|
| 58 |
+
return hashlib.sha256(value).hexdigest()
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def _digest_file(path: Path) -> str:
|
| 62 |
+
digest = hashlib.sha256()
|
| 63 |
+
with path.open("rb") as handle:
|
| 64 |
+
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
|
| 65 |
+
digest.update(chunk)
|
| 66 |
+
return digest.hexdigest()
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def _read_json(path: Path) -> dict[str, Any]:
|
| 70 |
+
value = json.loads(path.read_text(encoding="utf-8"))
|
| 71 |
+
if not isinstance(value, dict):
|
| 72 |
+
raise ValueError("JSON root must be an object")
|
| 73 |
+
return value
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def _load_manifest() -> dict[str, Any]:
|
| 77 |
+
value = _read_json(MANIFEST_PATH)
|
| 78 |
+
if value.get("schema") != "szl.m1-operational-manifest/v1":
|
| 79 |
+
raise ValueError("unsupported M1 manifest schema")
|
| 80 |
+
if value.get("release_state") != "NOT_PROMOTED":
|
| 81 |
+
raise ValueError("M1 manifest must remain NOT_PROMOTED")
|
| 82 |
+
if (value.get("inference_policy") or {}).get("production_eligible") is not False:
|
| 83 |
+
raise ValueError("M1 production eligibility must be false")
|
| 84 |
+
return value
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def _result(state: str, reason: str, **evidence: Any) -> dict[str, Any]:
|
| 88 |
+
return {"state": state, "reason": reason, **evidence}
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def _configured_root(env_name: str) -> Path | None:
|
| 92 |
+
raw = os.environ.get(env_name, "").strip()
|
| 93 |
+
if not raw:
|
| 94 |
+
return None
|
| 95 |
+
try:
|
| 96 |
+
return Path(raw).expanduser().resolve(strict=False)
|
| 97 |
+
except (OSError, RuntimeError):
|
| 98 |
+
return None
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def _confined_file(root: Path, relative: str) -> Path:
|
| 102 |
+
if not relative or Path(relative).is_absolute():
|
| 103 |
+
raise ValueError("artifact path must be relative")
|
| 104 |
+
target = (root / relative).resolve(strict=False)
|
| 105 |
+
try:
|
| 106 |
+
target.relative_to(root.resolve(strict=False))
|
| 107 |
+
except ValueError as exc:
|
| 108 |
+
raise ValueError("artifact path escapes configured root") from exc
|
| 109 |
+
return target
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
def _verify_file(root: Path | None, spec: dict[str, Any]) -> dict[str, Any]:
|
| 113 |
+
relative = str(spec.get("path") or "")
|
| 114 |
+
public = {"path": relative, "expected_sha256": spec.get("sha256"), "expected_bytes": spec.get("bytes")}
|
| 115 |
+
if root is None:
|
| 116 |
+
return _result(UNAVAILABLE, "artifact root is not configured", **public)
|
| 117 |
+
try:
|
| 118 |
+
path = _confined_file(root, relative)
|
| 119 |
+
except ValueError as exc:
|
| 120 |
+
return _result(BLOCKED, str(exc), **public)
|
| 121 |
+
if not path.is_file():
|
| 122 |
+
return _result(UNAVAILABLE, "required local artifact is absent", **public)
|
| 123 |
+
try:
|
| 124 |
+
size = path.stat().st_size
|
| 125 |
+
expected_size = int(spec["bytes"])
|
| 126 |
+
if size != expected_size:
|
| 127 |
+
return _result(BLOCKED, "artifact byte length mismatch", actual_bytes=size, **public)
|
| 128 |
+
digest = _digest_file(path)
|
| 129 |
+
except (OSError, ValueError, KeyError) as exc:
|
| 130 |
+
return _result(UNAVAILABLE, f"artifact could not be verified ({type(exc).__name__})", **public)
|
| 131 |
+
if digest != str(spec.get("sha256") or "").lower():
|
| 132 |
+
return _result(BLOCKED, "artifact SHA-256 mismatch", actual_sha256=digest, **public)
|
| 133 |
+
return _result(PASS, "exact byte length and SHA-256 match", actual_sha256=digest, actual_bytes=size, **public)
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def _rollup_files(root: Path | None, specs: list[dict[str, Any]], label: str) -> dict[str, Any]:
|
| 137 |
+
files = [_verify_file(root, spec) for spec in specs]
|
| 138 |
+
states = {entry["state"] for entry in files}
|
| 139 |
+
state = BLOCKED if BLOCKED in states else UNAVAILABLE if UNAVAILABLE in states else PASS
|
| 140 |
+
return {
|
| 141 |
+
"state": state,
|
| 142 |
+
"reason": f"{label}: {sum(item['state'] == PASS for item in files)}/{len(files)} exact files verified",
|
| 143 |
+
"verified_files": sum(item["state"] == PASS for item in files),
|
| 144 |
+
"required_files": len(files),
|
| 145 |
+
"files": files,
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
def _json_after_verified(root: Path | None, spec: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any] | None]:
|
| 150 |
+
checked = _verify_file(root, spec)
|
| 151 |
+
if checked["state"] != PASS or root is None:
|
| 152 |
+
return checked, None
|
| 153 |
+
try:
|
| 154 |
+
return checked, _read_json(_confined_file(root, str(spec["path"])))
|
| 155 |
+
except (OSError, ValueError, KeyError, json.JSONDecodeError) as exc:
|
| 156 |
+
public = {key: value for key, value in checked.items() if key not in {"state", "reason"}}
|
| 157 |
+
return _result(BLOCKED, f"verified receipt is not valid JSON ({type(exc).__name__})", **public), None
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
def _metadata_evidence(manifest: dict[str, Any]) -> dict[str, Any]:
|
| 161 |
+
evidence = manifest["evidence"]
|
| 162 |
+
candidate_check, candidate = _json_after_verified(MANIFEST_DIR, evidence["candidate_manifest"])
|
| 163 |
+
evaluation_check, evaluation = _json_after_verified(MANIFEST_DIR, evidence["evaluation_manifest"])
|
| 164 |
+
if candidate_check["state"] != PASS or evaluation_check["state"] != PASS:
|
| 165 |
+
state = BLOCKED if BLOCKED in {candidate_check["state"], evaluation_check["state"]} else UNAVAILABLE
|
| 166 |
+
return _result(state, "candidate or evaluation manifest integrity failed", candidate=candidate_check, evaluation=evaluation_check)
|
| 167 |
+
|
| 168 |
+
expected_base = manifest["base"]
|
| 169 |
+
candidate_base = candidate.get("base") if candidate else {}
|
| 170 |
+
mismatches: list[str] = []
|
| 171 |
+
for key in ("repository", "revision", "architecture", "license", "license_evidence"):
|
| 172 |
+
if candidate_base.get(key) != expected_base.get(key):
|
| 173 |
+
mismatches.append(f"base.{key}")
|
| 174 |
+
if not candidate or candidate.get("candidate_id") != manifest["candidate_id"]:
|
| 175 |
+
mismatches.append("candidate_id")
|
| 176 |
+
if candidate and candidate.get("release_state") != "NOT_PROMOTED":
|
| 177 |
+
mismatches.append("release_state")
|
| 178 |
+
if candidate and candidate.get("quality_claim") != "NOT_ESTABLISHED":
|
| 179 |
+
mismatches.append("quality_claim")
|
| 180 |
+
if not evaluation or evaluation.get("candidate_id") != manifest["candidate_id"]:
|
| 181 |
+
mismatches.append("evaluation.candidate_id")
|
| 182 |
+
if evaluation and evaluation.get("promotion_decision") != "NOT_PROMOTED":
|
| 183 |
+
mismatches.append("evaluation.promotion_decision")
|
| 184 |
+
corpus_spec = (manifest.get("evidence") or {}).get("corpus_ingestion_manifest") or {}
|
| 185 |
+
corpus_policy = manifest.get("corpus_policy") or {}
|
| 186 |
+
proposal = (candidate or {}).get("full_corpus_proposal") or {}
|
| 187 |
+
expected_proposal = {
|
| 188 |
+
"relation": "PROPOSAL_ONLY_NOT_USED_BY_EXISTING_ADAPTER",
|
| 189 |
+
"manifest_path": corpus_spec.get("path"),
|
| 190 |
+
"manifest_sha256": corpus_spec.get("sha256"),
|
| 191 |
+
"brain_raw_nodes": corpus_policy.get("expected_raw_nodes"),
|
| 192 |
+
"brain_distinct_artifacts": corpus_policy.get("expected_distinct_artifacts"),
|
| 193 |
+
"formula_records": corpus_policy.get("expected_formula_records"),
|
| 194 |
+
"training_state": "NOT_RUN",
|
| 195 |
+
}
|
| 196 |
+
if proposal != expected_proposal:
|
| 197 |
+
mismatches.append("full_corpus_proposal")
|
| 198 |
+
reload_meta = ((evaluation or {}).get("measured") or {}).get("offline_reload") or {}
|
| 199 |
+
if reload_meta.get("state") != "PASS":
|
| 200 |
+
mismatches.append("evaluation.offline_reload.state")
|
| 201 |
+
if mismatches:
|
| 202 |
+
return _result(BLOCKED, "metadata consistency check failed", mismatches=mismatches,
|
| 203 |
+
candidate=candidate_check, evaluation=evaluation_check)
|
| 204 |
+
return _result(
|
| 205 |
+
PASS,
|
| 206 |
+
"immutable candidate and evaluation metadata are consistent",
|
| 207 |
+
candidate=candidate_check,
|
| 208 |
+
evaluation=evaluation_check,
|
| 209 |
+
repository=expected_base["repository"],
|
| 210 |
+
revision=expected_base["revision"],
|
| 211 |
+
architecture=expected_base["architecture"],
|
| 212 |
+
license=expected_base["license"],
|
| 213 |
+
license_evidence=expected_base["license_evidence"],
|
| 214 |
+
license_verification_scope="metadata consistency only; not an independent legal opinion",
|
| 215 |
+
evaluation_state=evaluation.get("evaluation_state"),
|
| 216 |
+
unrun_suites=list(evaluation.get("required_unrun_suites") or []),
|
| 217 |
+
corpus_relation=proposal.get("relation"), corpus_manifest_sha256=proposal.get("manifest_sha256"),
|
| 218 |
+
quality_claim="NOT_ESTABLISHED",
|
| 219 |
+
release_state="NOT_PROMOTED",
|
| 220 |
+
)
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
def _audit_corpus_ledger(spec: dict[str, Any], *, expected_schema: str,
|
| 224 |
+
evaluation_receipt_id: str, kind: str) -> dict[str, Any]:
|
| 225 |
+
checked = _verify_file(MANIFEST_DIR, spec)
|
| 226 |
+
if checked["state"] != PASS:
|
| 227 |
+
return checked
|
| 228 |
+
try:
|
| 229 |
+
path = _confined_file(MANIFEST_DIR, str(spec["path"]))
|
| 230 |
+
expected_rows = int(spec["rows"])
|
| 231 |
+
except (KeyError, TypeError, ValueError) as exc:
|
| 232 |
+
return _result(BLOCKED, f"ledger specification is invalid ({type(exc).__name__})", file=checked)
|
| 233 |
+
|
| 234 |
+
rows = 0
|
| 235 |
+
artifact_rows = 0
|
| 236 |
+
receipts: set[str] = set()
|
| 237 |
+
identities: set[str] = set()
|
| 238 |
+
family_splits: dict[str, str] = {}
|
| 239 |
+
decisions: Counter[str] = Counter()
|
| 240 |
+
formula_status: Counter[str] = Counter()
|
| 241 |
+
formula_bindings: dict[str, dict[str, str | None]] = {}
|
| 242 |
+
errors: list[str] = []
|
| 243 |
+
vocabulary = {"KERNEL_ACCEPTED", "CONDITIONAL", "OPEN", "REFUTED"}
|
| 244 |
+
try:
|
| 245 |
+
with path.open("r", encoding="utf-8") as stream:
|
| 246 |
+
for line_number, line in enumerate(stream, 1):
|
| 247 |
+
if not line.strip():
|
| 248 |
+
errors.append(f"line {line_number}: blank row")
|
| 249 |
+
continue
|
| 250 |
+
try:
|
| 251 |
+
row = json.loads(line)
|
| 252 |
+
except json.JSONDecodeError:
|
| 253 |
+
errors.append(f"line {line_number}: invalid JSON")
|
| 254 |
+
continue
|
| 255 |
+
rows += 1
|
| 256 |
+
if not isinstance(row, dict) or row.get("schema") != expected_schema:
|
| 257 |
+
errors.append(f"line {line_number}: schema mismatch")
|
| 258 |
+
continue
|
| 259 |
+
receipt_id = str(row.get("receipt_id") or "")
|
| 260 |
+
if not receipt_id or receipt_id in receipts:
|
| 261 |
+
errors.append(f"line {line_number}: absent or duplicate receipt_id")
|
| 262 |
+
receipts.add(receipt_id)
|
| 263 |
+
identity = str(row.get("node_id") if kind == "brain" else f"{row.get('source_family')}:{row.get('formula_id')}")
|
| 264 |
+
if not identity or identity in identities:
|
| 265 |
+
errors.append(f"line {line_number}: absent or duplicate row identity")
|
| 266 |
+
identities.add(identity)
|
| 267 |
+
if row.get("evaluation_receipt_id") != evaluation_receipt_id:
|
| 268 |
+
errors.append(f"line {line_number}: evaluation receipt binding mismatch")
|
| 269 |
+
canonical_text = row.get("canonical_text")
|
| 270 |
+
if not isinstance(canonical_text, str) or not canonical_text:
|
| 271 |
+
errors.append(f"line {line_number}: canonical text absent")
|
| 272 |
+
elif _digest_bytes(canonical_text.encode("utf-8")) != row.get("canonical_text_sha256"):
|
| 273 |
+
errors.append(f"line {line_number}: canonical text digest mismatch")
|
| 274 |
+
family = str(row.get("source_family") or "")
|
| 275 |
+
split = str(row.get("source_family_split") or "")
|
| 276 |
+
if not family or split not in {"TRAIN", "HOLDOUT", "QUARANTINE"}:
|
| 277 |
+
errors.append(f"line {line_number}: invalid source-family split")
|
| 278 |
+
elif family in family_splits and family_splits[family] != split:
|
| 279 |
+
errors.append(f"line {line_number}: source family crosses partitions")
|
| 280 |
+
else:
|
| 281 |
+
family_splits[family] = split
|
| 282 |
+
decision = str(row.get("training_decision") or "")
|
| 283 |
+
decisions[decision] += 1
|
| 284 |
+
if kind == "brain":
|
| 285 |
+
if row.get("brain_anatomy_receipt_id") != receipt_id or not receipt_id.startswith("brain-node:sha256:"):
|
| 286 |
+
errors.append(f"line {line_number}: Brain Anatomy receipt binding mismatch")
|
| 287 |
+
if row.get("artifact_role") == "DISTINCT_ARTIFACT":
|
| 288 |
+
artifact_rows += 1
|
| 289 |
+
license_state = ((row.get("license") or {}).get("state"))
|
| 290 |
+
if license_state == "UNKNOWN_ITEM_LEVEL_LICENSE" and decision != "QUARANTINE":
|
| 291 |
+
errors.append(f"line {line_number}: unknown-license row escaped quarantine")
|
| 292 |
+
if row.get("formula_status") is not None:
|
| 293 |
+
formula_id = str(row.get("formula_id") or "")
|
| 294 |
+
if (not formula_id or formula_id in formula_bindings or
|
| 295 |
+
row.get("formula_status") not in vocabulary or
|
| 296 |
+
not str(row.get("formula_receipt_id") or "").startswith("formula:sha256:")):
|
| 297 |
+
errors.append(f"line {line_number}: formula node status/receipt invalid")
|
| 298 |
+
else:
|
| 299 |
+
formula_bindings[formula_id] = {
|
| 300 |
+
"formula_receipt_id": str(row["formula_receipt_id"]),
|
| 301 |
+
"brain_anatomy_receipt_id": receipt_id,
|
| 302 |
+
}
|
| 303 |
+
else:
|
| 304 |
+
status = str(row.get("formula_status") or "")
|
| 305 |
+
formula_status[status] += 1
|
| 306 |
+
if not receipt_id.startswith("formula:sha256:") or row.get("formula_receipt_id") != receipt_id:
|
| 307 |
+
errors.append(f"line {line_number}: formula receipt binding mismatch")
|
| 308 |
+
if status not in vocabulary or split != "HOLDOUT":
|
| 309 |
+
errors.append(f"line {line_number}: formula status/split invalid")
|
| 310 |
+
expected_role = "HOLDOUT_POSITIVE" if status == "KERNEL_ACCEPTED" else (
|
| 311 |
+
"HOLDOUT_NEGATIVE" if status == "REFUTED" else "HOLDOUT_ABSTENTION"
|
| 312 |
+
)
|
| 313 |
+
if decision != expected_role:
|
| 314 |
+
errors.append(f"line {line_number}: formula role does not match status")
|
| 315 |
+
if bool(row.get("abstention_required")) != (status in {"OPEN", "CONDITIONAL"}):
|
| 316 |
+
errors.append(f"line {line_number}: abstention label mismatch")
|
| 317 |
+
if bool(row.get("negative_example")) != (status == "REFUTED"):
|
| 318 |
+
errors.append(f"line {line_number}: negative-example label mismatch")
|
| 319 |
+
if row.get("brain_anatomy_receipt_id"):
|
| 320 |
+
formula_bindings[str(row.get("formula_id") or "")] = {
|
| 321 |
+
"formula_receipt_id": receipt_id,
|
| 322 |
+
"brain_anatomy_receipt_id": str(row["brain_anatomy_receipt_id"]),
|
| 323 |
+
}
|
| 324 |
+
if len(errors) >= 20:
|
| 325 |
+
break
|
| 326 |
+
except OSError as exc:
|
| 327 |
+
return _result(UNAVAILABLE, f"ledger could not be read ({type(exc).__name__})", file=checked)
|
| 328 |
+
|
| 329 |
+
if rows != expected_rows:
|
| 330 |
+
errors.append(f"row count {rows} != expected {expected_rows}")
|
| 331 |
+
if errors:
|
| 332 |
+
return _result(BLOCKED, "corpus ledger semantic verification failed", file=checked,
|
| 333 |
+
errors=errors[:20], rows_observed=rows, rows_expected=expected_rows)
|
| 334 |
+
return _result(
|
| 335 |
+
PASS, "exact ledger bytes and every decision row verified",
|
| 336 |
+
file=checked, rows=rows, distinct_artifact_rows=artifact_rows,
|
| 337 |
+
source_family_split=dict(sorted(family_splits.items())),
|
| 338 |
+
decisions=dict(sorted(decisions.items())), formula_status=dict(sorted(formula_status.items())),
|
| 339 |
+
formula_bindings=dict(sorted(formula_bindings.items())),
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
def _corpus_evidence(manifest: dict[str, Any]) -> dict[str, Any]:
|
| 344 |
+
evidence = manifest.get("evidence") or {}
|
| 345 |
+
policy = manifest.get("corpus_policy") or {}
|
| 346 |
+
try:
|
| 347 |
+
summary_check, summary = _json_after_verified(MANIFEST_DIR, evidence["corpus_ingestion_manifest"])
|
| 348 |
+
if summary_check["state"] != PASS or summary is None:
|
| 349 |
+
return summary_check
|
| 350 |
+
if summary.get("schema") != "szl.m1-corpus-ingestion-manifest/v1":
|
| 351 |
+
return _result(BLOCKED, "corpus ingestion manifest schema mismatch", file=summary_check)
|
| 352 |
+
evaluation_spec = evidence["evaluation_manifest"]
|
| 353 |
+
evaluation_receipt_id = f"m1-evaluation:sha256:{evaluation_spec['sha256']}"
|
| 354 |
+
brain = _audit_corpus_ledger(
|
| 355 |
+
evidence["brain_ingest_ledger"], expected_schema="szl.m1-brain-ingest-decision/v1",
|
| 356 |
+
evaluation_receipt_id=evaluation_receipt_id, kind="brain",
|
| 357 |
+
)
|
| 358 |
+
formulas = _audit_corpus_ledger(
|
| 359 |
+
evidence["formula_curriculum_ledger"], expected_schema="szl.m1-formula-curriculum-decision/v1",
|
| 360 |
+
evaluation_receipt_id=evaluation_receipt_id, kind="formula",
|
| 361 |
+
)
|
| 362 |
+
except (KeyError, TypeError, ValueError) as exc:
|
| 363 |
+
return _result(BLOCKED, f"corpus evidence configuration invalid ({type(exc).__name__})")
|
| 364 |
+
if BLOCKED in {brain["state"], formulas["state"]}:
|
| 365 |
+
return _result(BLOCKED, "corpus ledger integrity or semantic gate failed", manifest=summary_check,
|
| 366 |
+
brain_ledger=brain, formula_ledger=formulas)
|
| 367 |
+
if UNAVAILABLE in {brain["state"], formulas["state"]}:
|
| 368 |
+
return _result(UNAVAILABLE, "corpus ledger is unavailable", manifest=summary_check,
|
| 369 |
+
brain_ledger=brain, formula_ledger=formulas)
|
| 370 |
+
|
| 371 |
+
coverage = summary.get("coverage") or {}
|
| 372 |
+
source = summary.get("source_snapshot") or {}
|
| 373 |
+
ledgers = summary.get("ledgers") or {}
|
| 374 |
+
resulting = summary.get("resulting_evaluation_receipt") or {}
|
| 375 |
+
expected_nodes = int(policy.get("expected_raw_nodes", -1))
|
| 376 |
+
expected_artifacts = int(policy.get("expected_distinct_artifacts", -1))
|
| 377 |
+
expected_formulas = int(policy.get("expected_formula_records", -1))
|
| 378 |
+
mismatches: list[str] = []
|
| 379 |
+
if summary.get("candidate_id") != manifest.get("candidate_id"):
|
| 380 |
+
mismatches.append("candidate_id")
|
| 381 |
+
if summary.get("release_state") != "NOT_PROMOTED" or summary.get("training_state") != "NOT_RUN":
|
| 382 |
+
mismatches.append("release/training state")
|
| 383 |
+
if summary.get("training_relation") != policy.get("training_relation"):
|
| 384 |
+
mismatches.append("training relation")
|
| 385 |
+
if source.get("raw_node_count") != expected_nodes or brain.get("rows") != expected_nodes:
|
| 386 |
+
mismatches.append("raw node coverage")
|
| 387 |
+
if source.get("distinct_artifact_count") != expected_artifacts or brain.get("distinct_artifact_rows") != expected_artifacts:
|
| 388 |
+
mismatches.append("distinct artifact coverage")
|
| 389 |
+
if coverage.get("node_decisions_total") != expected_nodes or coverage.get("node_decisions_expected") != expected_nodes or coverage.get("node_decision_coverage") != 1.0:
|
| 390 |
+
mismatches.append("decision coverage")
|
| 391 |
+
if policy.get("require_raw_brain_training_quarantine") is True and (
|
| 392 |
+
coverage.get("raw_nodes_training_quarantined") != expected_nodes
|
| 393 |
+
or coverage.get("training_eligible_nodes") != 0
|
| 394 |
+
or brain.get("decisions") != {"QUARANTINE": expected_nodes}
|
| 395 |
+
):
|
| 396 |
+
mismatches.append("raw Brain training quarantine")
|
| 397 |
+
if coverage.get("formula_records_current_versioned_sources") != expected_formulas or formulas.get("rows") != expected_formulas:
|
| 398 |
+
mismatches.append("formula coverage")
|
| 399 |
+
if resulting.get("receipt_id") != evaluation_receipt_id or resulting.get("sha256") != evaluation_spec.get("sha256"):
|
| 400 |
+
mismatches.append("evaluation receipt binding")
|
| 401 |
+
if resulting.get("state") != "INCOMPLETE" or resulting.get("promotion_decision") != "NOT_PROMOTED":
|
| 402 |
+
mismatches.append("evaluation/promotion boundary")
|
| 403 |
+
if brain.get("formula_bindings") != formulas.get("formula_bindings"):
|
| 404 |
+
mismatches.append("Brain/formula Anatomy receipt crosswalk")
|
| 405 |
+
for summary_name, evidence_name in (("brain_nodes", "brain_ingest_ledger"), ("formulas", "formula_curriculum_ledger")):
|
| 406 |
+
declared = ledgers.get(summary_name) or {}
|
| 407 |
+
expected = evidence.get(evidence_name) or {}
|
| 408 |
+
if any(declared.get(key) != expected.get(key) for key in ("path", "bytes", "sha256")):
|
| 409 |
+
mismatches.append(f"{summary_name} ledger binding")
|
| 410 |
+
family_split = summary.get("source_family_split") or {}
|
| 411 |
+
if policy.get("require_source_family_isolation") is not True or any(
|
| 412 |
+
not isinstance(value, dict) or value.get("split") not in {"TRAIN", "HOLDOUT", "QUARANTINE"}
|
| 413 |
+
for value in family_split.values()
|
| 414 |
+
):
|
| 415 |
+
mismatches.append("source family isolation")
|
| 416 |
+
if policy.get("allow_unknown_license_for_training") is not False:
|
| 417 |
+
mismatches.append("unknown-license policy")
|
| 418 |
+
if policy.get("require_raw_brain_training_quarantine") is not True:
|
| 419 |
+
mismatches.append("raw Brain quarantine policy")
|
| 420 |
+
if mismatches:
|
| 421 |
+
return _result(BLOCKED, "corpus manifest coverage contract mismatch", mismatches=mismatches,
|
| 422 |
+
manifest=summary_check, brain_ledger=brain, formula_ledger=formulas)
|
| 423 |
+
return _result(
|
| 424 |
+
PASS,
|
| 425 |
+
"full Brain decision coverage and formula holdout curriculum verified; quarantines retained",
|
| 426 |
+
manifest=summary_check, brain_ledger=brain, formula_ledger=formulas,
|
| 427 |
+
corpus_receipt_id=f"m1-corpus:sha256:{evidence['corpus_ingestion_manifest']['sha256']}",
|
| 428 |
+
evaluation_receipt_id=evaluation_receipt_id,
|
| 429 |
+
coverage=coverage, source_snapshot=source, source_family_split=family_split,
|
| 430 |
+
training_state="NOT_RUN", training_relation=summary.get("training_relation"),
|
| 431 |
+
quality_claim="NOT_ESTABLISHED", release_state="NOT_PROMOTED",
|
| 432 |
+
)
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
def _training_evidence(manifest: dict[str, Any], run_root: Path | None) -> dict[str, Any]:
|
| 436 |
+
checked, receipt = _json_after_verified(run_root, manifest["evidence"]["training_receipt"])
|
| 437 |
+
if checked["state"] != PASS or receipt is None:
|
| 438 |
+
return checked
|
| 439 |
+
mismatches: list[str] = []
|
| 440 |
+
base = receipt.get("base_model") or {}
|
| 441 |
+
if receipt.get("schema") != "szl.bounded-lora-training-receipt/v1":
|
| 442 |
+
mismatches.append("schema")
|
| 443 |
+
if receipt.get("state") != "COMPLETED":
|
| 444 |
+
mismatches.append("state")
|
| 445 |
+
if receipt.get("evidence_label") != "MEASURED":
|
| 446 |
+
mismatches.append("evidence_label")
|
| 447 |
+
if receipt.get("receipt_sha256") != manifest["evidence"]["training_receipt"]["internal_sha256"]:
|
| 448 |
+
mismatches.append("receipt_sha256")
|
| 449 |
+
if base.get("repo") != manifest["base"]["repository"]:
|
| 450 |
+
mismatches.append("base_model.repo")
|
| 451 |
+
if base.get("revision") != manifest["base"]["revision"]:
|
| 452 |
+
mismatches.append("base_model.revision")
|
| 453 |
+
if base.get("network_download_allowed") is not False:
|
| 454 |
+
mismatches.append("base_model.network_download_allowed")
|
| 455 |
+
if (receipt.get("evaluation") or {}).get("quality_claim") != "NOT_ESTABLISHED":
|
| 456 |
+
mismatches.append("evaluation.quality_claim")
|
| 457 |
+
if (receipt.get("artifacts") or {}).get("promotion_state") != "NOT_PROMOTED":
|
| 458 |
+
mismatches.append("artifacts.promotion_state")
|
| 459 |
+
receipt_files = {item.get("path"): item for item in (receipt.get("artifacts") or {}).get("files", [])}
|
| 460 |
+
for expected in manifest["adapter"]["files"]:
|
| 461 |
+
actual = receipt_files.get(expected["path"])
|
| 462 |
+
if not actual or actual.get("sha256") != expected["sha256"] or actual.get("bytes") != expected["bytes"]:
|
| 463 |
+
mismatches.append(f"artifacts.files:{expected['path']}")
|
| 464 |
+
if mismatches:
|
| 465 |
+
return _result(BLOCKED, "training receipt content does not match the operational manifest",
|
| 466 |
+
mismatches=mismatches, file=checked)
|
| 467 |
+
return _result(PASS, "training receipt integrity and lineage match", file=checked,
|
| 468 |
+
measured_state="COMPLETED", quality_claim="NOT_ESTABLISHED",
|
| 469 |
+
release_state="NOT_PROMOTED")
|
| 470 |
+
|
| 471 |
+
|
| 472 |
+
def _reload_evidence(manifest: dict[str, Any], run_root: Path | None) -> dict[str, Any]:
|
| 473 |
+
checked, receipt = _json_after_verified(run_root, manifest["evidence"]["reload_receipt"])
|
| 474 |
+
if checked["state"] != PASS or receipt is None:
|
| 475 |
+
return checked
|
| 476 |
+
adapter_sha = next(
|
| 477 |
+
item["sha256"] for item in manifest["adapter"]["files"]
|
| 478 |
+
if item["path"] == "adapter/adapter_model.safetensors"
|
| 479 |
+
)
|
| 480 |
+
mismatches = []
|
| 481 |
+
if receipt.get("schema") != "szl.adapter-reload-smoke/v1":
|
| 482 |
+
mismatches.append("schema")
|
| 483 |
+
if receipt.get("state") != "PASS":
|
| 484 |
+
mismatches.append("state")
|
| 485 |
+
if receipt.get("offline") is not True:
|
| 486 |
+
mismatches.append("offline")
|
| 487 |
+
if receipt.get("adapter_model_sha256") != adapter_sha:
|
| 488 |
+
mismatches.append("adapter_model_sha256")
|
| 489 |
+
if not receipt.get("generated_text_sha256"):
|
| 490 |
+
mismatches.append("generated_text_sha256")
|
| 491 |
+
if mismatches:
|
| 492 |
+
return _result(BLOCKED, "offline reload receipt content mismatch", mismatches=mismatches, file=checked)
|
| 493 |
+
return _result(PASS, "offline reload receipt verified", file=checked,
|
| 494 |
+
interpretation="COMPATIBILITY_ONLY_NOT_QUALITY",
|
| 495 |
+
generated_text_sha256=receipt["generated_text_sha256"])
|
| 496 |
+
|
| 497 |
+
|
| 498 |
+
def _runtime_provider(manifest: dict[str, Any]) -> dict[str, Any]:
|
| 499 |
+
expected = manifest["provider"]["id"]
|
| 500 |
+
configured = os.environ.get("A11OY_M1_PROVIDER_ID", "").strip()
|
| 501 |
+
if os.environ.get("A11OY_M1_BASE_URL", "").strip():
|
| 502 |
+
return _result(BLOCKED, "remote provider/base URL is forbidden for M1", expected_provider_id=expected)
|
| 503 |
+
if not configured:
|
| 504 |
+
return _result(UNAVAILABLE, "A11OY_M1_PROVIDER_ID is not configured", expected_provider_id=expected)
|
| 505 |
+
if configured != expected:
|
| 506 |
+
return _result(BLOCKED, "configured provider identity mismatch", expected_provider_id=expected)
|
| 507 |
+
packages = {name: importlib.util.find_spec(name) is not None for name in ("torch", "transformers", "peft")}
|
| 508 |
+
if not all(packages.values()):
|
| 509 |
+
return _result(UNAVAILABLE, "local PEFT runtime dependencies are unavailable",
|
| 510 |
+
provider_id=configured, transport="IN_PROCESS_ONLY", packages=packages)
|
| 511 |
+
return _result(PASS, "exact local in-process provider identity and runtime are available",
|
| 512 |
+
provider_id=configured, transport="IN_PROCESS_ONLY", network_allowed=False, packages=packages)
|
| 513 |
+
|
| 514 |
+
|
| 515 |
+
def _gpu_snapshot() -> dict[str, Any]:
|
| 516 |
+
executable = shutil.which("nvidia-smi") or shutil.which("nvidia-smi.exe")
|
| 517 |
+
if not executable:
|
| 518 |
+
return _result(UNAVAILABLE, "nvidia-smi is unavailable")
|
| 519 |
+
query = [
|
| 520 |
+
executable,
|
| 521 |
+
"--query-gpu=index,name,memory.total,memory.free,utilization.gpu,temperature.gpu",
|
| 522 |
+
"--format=csv,noheader,nounits",
|
| 523 |
+
]
|
| 524 |
+
try:
|
| 525 |
+
completed = subprocess.run(query, capture_output=True, text=True, timeout=3, check=False, shell=False)
|
| 526 |
+
except (OSError, subprocess.SubprocessError) as exc:
|
| 527 |
+
return _result(UNAVAILABLE, f"GPU telemetry unavailable ({type(exc).__name__})")
|
| 528 |
+
if completed.returncode != 0:
|
| 529 |
+
return _result(UNAVAILABLE, "nvidia-smi telemetry command failed")
|
| 530 |
+
target = os.environ.get("A11OY_M1_GPU_INDEX", "0").strip()
|
| 531 |
+
rows = []
|
| 532 |
+
for raw in completed.stdout.splitlines():
|
| 533 |
+
parts = [part.strip() for part in raw.split(",")]
|
| 534 |
+
if len(parts) != 6:
|
| 535 |
+
continue
|
| 536 |
+
try:
|
| 537 |
+
rows.append({
|
| 538 |
+
"index": parts[0], "name": parts[1], "total_memory_mib": int(float(parts[2])),
|
| 539 |
+
"free_memory_mib": int(float(parts[3])), "utilization_pct": int(float(parts[4])),
|
| 540 |
+
"temperature_c": int(float(parts[5])),
|
| 541 |
+
})
|
| 542 |
+
except ValueError:
|
| 543 |
+
continue
|
| 544 |
+
selected = next((row for row in rows if row["index"] == target), None)
|
| 545 |
+
if selected is None:
|
| 546 |
+
return _result(UNAVAILABLE, "configured GPU index was not reported", gpu_index=target)
|
| 547 |
+
return _result(PASS, "live GPU telemetry measured", **selected)
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
def _gpu_admission(manifest: dict[str, Any]) -> dict[str, Any]:
|
| 551 |
+
snapshot = _gpu_snapshot()
|
| 552 |
+
if snapshot["state"] != PASS:
|
| 553 |
+
return snapshot
|
| 554 |
+
policy = manifest["gpu_admission"]
|
| 555 |
+
reasons = []
|
| 556 |
+
if snapshot["name"] != manifest["provider"]["expected_gpu_name"]:
|
| 557 |
+
reasons.append("GPU identity mismatch")
|
| 558 |
+
if snapshot["free_memory_mib"] < policy["minimum_free_memory_mib"]:
|
| 559 |
+
reasons.append("insufficient free GPU memory")
|
| 560 |
+
if snapshot["utilization_pct"] > policy["maximum_utilization_pct"]:
|
| 561 |
+
reasons.append("GPU utilization exceeds admission ceiling")
|
| 562 |
+
if snapshot["temperature_c"] > policy["maximum_temperature_c"]:
|
| 563 |
+
reasons.append("GPU temperature exceeds admission ceiling")
|
| 564 |
+
if reasons:
|
| 565 |
+
return _result(BLOCKED, "; ".join(reasons), telemetry=snapshot, policy=policy)
|
| 566 |
+
return _result(PASS, "live GPU identity and resource admission pass", telemetry=snapshot, policy=policy)
|
| 567 |
+
|
| 568 |
+
|
| 569 |
+
def operational_status() -> dict[str, Any]:
|
| 570 |
+
try:
|
| 571 |
+
manifest = _load_manifest()
|
| 572 |
+
except (OSError, ValueError, json.JSONDecodeError, KeyError) as exc:
|
| 573 |
+
return {
|
| 574 |
+
"schema": SCHEMA, "candidate_id": "a11oy-evidence-1.5b-sft-lora",
|
| 575 |
+
"operational_state": BLOCKED, "release_state": "NOT_PROMOTED",
|
| 576 |
+
"production_eligible": False, "inference_mode": "DISABLED",
|
| 577 |
+
"reason": f"operational manifest invalid ({type(exc).__name__})", "checks": {},
|
| 578 |
+
}
|
| 579 |
+
|
| 580 |
+
run_root = _configured_root("A11OY_M1_RUN_ROOT")
|
| 581 |
+
base_root = _configured_root("A11OY_M1_BASE_SNAPSHOT")
|
| 582 |
+
metadata = _metadata_evidence(manifest)
|
| 583 |
+
corpus = _corpus_evidence(manifest)
|
| 584 |
+
base = _rollup_files(base_root, manifest["base"]["files"], "base snapshot")
|
| 585 |
+
adapter = _rollup_files(run_root, manifest["adapter"]["files"], "adapter")
|
| 586 |
+
training = _training_evidence(manifest, run_root)
|
| 587 |
+
reload = _reload_evidence(manifest, run_root)
|
| 588 |
+
provider = _runtime_provider(manifest)
|
| 589 |
+
gpu = _gpu_admission(manifest)
|
| 590 |
+
|
| 591 |
+
tokenizer_paths = {"added_tokens.json", "merges.txt", "special_tokens_map.json", "tokenizer.json", "tokenizer_config.json", "vocab.json"}
|
| 592 |
+
tokenizer_files = [item for item in base["files"] if item["path"] in tokenizer_paths]
|
| 593 |
+
tokenizer_state = BLOCKED if any(item["state"] == BLOCKED for item in tokenizer_files) else (
|
| 594 |
+
UNAVAILABLE if any(item["state"] == UNAVAILABLE for item in tokenizer_files) else PASS
|
| 595 |
+
)
|
| 596 |
+
tokenizer = {
|
| 597 |
+
"state": tokenizer_state,
|
| 598 |
+
"reason": f"tokenizer: {sum(item['state'] == PASS for item in tokenizer_files)}/{len(tokenizer_files)} exact files verified",
|
| 599 |
+
"files": tokenizer_files,
|
| 600 |
+
}
|
| 601 |
+
checks = {
|
| 602 |
+
"metadata": metadata, "corpus_ingestion": corpus,
|
| 603 |
+
"base_weights": base, "adapter_weights": adapter,
|
| 604 |
+
"tokenizer": tokenizer, "training_receipt": training, "offline_reload": reload,
|
| 605 |
+
"evaluation_receipt": {
|
| 606 |
+
"state": metadata["state"],
|
| 607 |
+
"reason": "evaluation receipt integrity verified; broad quality evaluation remains incomplete" if metadata["state"] == PASS else metadata["reason"],
|
| 608 |
+
"quality_claim": "NOT_ESTABLISHED", "release_state": "NOT_PROMOTED",
|
| 609 |
+
"evaluation_state": metadata.get("evaluation_state"), "unrun_suites": metadata.get("unrun_suites", []),
|
| 610 |
+
},
|
| 611 |
+
"provider_identity": provider, "gpu_admission": gpu,
|
| 612 |
+
}
|
| 613 |
+
mandatory = [entry["state"] for entry in checks.values()]
|
| 614 |
+
state = BLOCKED if BLOCKED in mandatory else UNAVAILABLE if UNAVAILABLE in mandatory else READY
|
| 615 |
+
enabled = state == READY
|
| 616 |
+
stages = {
|
| 617 |
+
"corpus": {
|
| 618 |
+
"state": "FULL_DECISION_LEDGER_VERIFIED" if corpus["state"] == PASS else corpus["state"],
|
| 619 |
+
"raw_nodes": (corpus.get("coverage") or {}).get("node_decisions_total"),
|
| 620 |
+
"distinct_artifacts": (corpus.get("coverage") or {}).get("distinct_artifacts"),
|
| 621 |
+
"quarantined_or_excluded": (corpus.get("coverage") or {}).get("quarantined_or_excluded_nodes"),
|
| 622 |
+
"formula_records": (corpus.get("coverage") or {}).get("formula_records_current_versioned_sources"),
|
| 623 |
+
"training": "NOT_RUN",
|
| 624 |
+
},
|
| 625 |
+
"weights": {"state": PASS if base["state"] == adapter["state"] == tokenizer["state"] == PASS else state,
|
| 626 |
+
"base": base["state"], "adapter": adapter["state"], "tokenizer": tokenizer["state"]},
|
| 627 |
+
"load": {"state": "READY_TO_LOAD" if provider["state"] == reload["state"] == gpu["state"] == PASS else state,
|
| 628 |
+
"provider": provider["state"], "offline_reload": reload["state"], "gpu": gpu["state"]},
|
| 629 |
+
"evaluation": {"state": "EVIDENCE_VERIFIED_WITH_LIMITS" if metadata["state"] == PASS else metadata["state"],
|
| 630 |
+
"quality_claim": "NOT_ESTABLISHED", "promotion": "NOT_PROMOTED"},
|
| 631 |
+
"inference": {"state": "ENABLED_EXPERIMENTAL_LOCAL_ONLY" if enabled else "DISABLED",
|
| 632 |
+
"production": "BLOCKED", "network": "DISABLED"},
|
| 633 |
+
}
|
| 634 |
+
return {
|
| 635 |
+
"schema": SCHEMA, "candidate_id": manifest["candidate_id"], "checked_at": _now(),
|
| 636 |
+
"operational_state": state, "release_state": "NOT_PROMOTED", "quality_claim": "NOT_ESTABLISHED",
|
| 637 |
+
"production_eligible": False, "inference_mode": "EXPERIMENTAL_LOCAL_ONLY" if enabled else "DISABLED",
|
| 638 |
+
"effectors": {"network": "DISABLED", "download": "DISABLED", "training": "DISABLED", "publishing": "DISABLED"},
|
| 639 |
+
"configured": {"run_root": run_root is not None, "base_snapshot": base_root is not None,
|
| 640 |
+
"provider_identity": bool(os.environ.get("A11OY_M1_PROVIDER_ID", "").strip())},
|
| 641 |
+
"stages": stages, "checks": checks,
|
| 642 |
+
"corpus_coverage": corpus.get("coverage", {}),
|
| 643 |
+
}
|
| 644 |
+
|
| 645 |
+
|
| 646 |
+
async def _bounded_json(request: Request, maximum: int) -> dict[str, Any]:
|
| 647 |
+
declared = request.headers.get("content-length")
|
| 648 |
+
if declared is not None:
|
| 649 |
+
try:
|
| 650 |
+
if int(declared) < 0 or int(declared) > maximum:
|
| 651 |
+
raise ContractError(f"request body exceeds {maximum} bytes")
|
| 652 |
+
except ValueError as exc:
|
| 653 |
+
raise ContractError("content-length must be a non-negative integer") from exc
|
| 654 |
+
body = bytearray()
|
| 655 |
+
async for chunk in request.stream():
|
| 656 |
+
if len(body) + len(chunk) > maximum:
|
| 657 |
+
raise ContractError(f"request body exceeds {maximum} bytes")
|
| 658 |
+
body.extend(chunk)
|
| 659 |
+
try:
|
| 660 |
+
value = json.loads(bytes(body).decode("utf-8"))
|
| 661 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 662 |
+
raise ContractError("body must be one JSON object") from exc
|
| 663 |
+
if not isinstance(value, dict):
|
| 664 |
+
raise ContractError("body must be one JSON object")
|
| 665 |
+
return value
|
| 666 |
+
|
| 667 |
+
|
| 668 |
+
def _parse_inference_request(payload: dict[str, Any], manifest: dict[str, Any]) -> dict[str, Any]:
|
| 669 |
+
required = {"schema", "prompt", "max_new_tokens", "temperature", "requested_tier", "provider_id"}
|
| 670 |
+
if set(payload) != required:
|
| 671 |
+
raise ContractError(f"fields must be exactly {sorted(required)}")
|
| 672 |
+
if payload.get("schema") != INFER_SCHEMA:
|
| 673 |
+
raise ContractError("unsupported inference request schema")
|
| 674 |
+
if payload.get("requested_tier") != "EXPERIMENTAL_LOCAL_ONLY":
|
| 675 |
+
raise ContractError("production and promoted tiers are forbidden for M1")
|
| 676 |
+
if payload.get("provider_id") != manifest["provider"]["id"]:
|
| 677 |
+
raise ContractError("request provider identity mismatch")
|
| 678 |
+
prompt = payload.get("prompt")
|
| 679 |
+
if not isinstance(prompt, str) or not prompt.strip() or len(prompt) > manifest["inference_policy"]["max_prompt_chars"]:
|
| 680 |
+
raise ContractError("prompt must be non-empty and within the character limit")
|
| 681 |
+
if any(ord(char) < 32 and char not in "\n\t\r" for char in prompt):
|
| 682 |
+
raise ContractError("prompt contains disallowed control characters")
|
| 683 |
+
max_new_tokens = payload.get("max_new_tokens")
|
| 684 |
+
if not isinstance(max_new_tokens, int) or isinstance(max_new_tokens, bool) or not 1 <= max_new_tokens <= manifest["inference_policy"]["max_new_tokens"]:
|
| 685 |
+
raise ContractError("max_new_tokens is outside the bounded policy")
|
| 686 |
+
temperature = payload.get("temperature")
|
| 687 |
+
if not isinstance(temperature, (int, float)) or isinstance(temperature, bool) or not 0 <= float(temperature) <= 1:
|
| 688 |
+
raise ContractError("temperature must be within [0,1]")
|
| 689 |
+
return {"prompt": prompt, "max_new_tokens": max_new_tokens, "temperature": float(temperature),
|
| 690 |
+
"provider_id": payload["provider_id"]}
|
| 691 |
+
|
| 692 |
+
|
| 693 |
+
def _local_peft_inference(parsed: dict[str, Any], manifest: dict[str, Any]) -> str:
|
| 694 |
+
"""Load exact local paths with local_files_only and run one bounded turn."""
|
| 695 |
+
import torch
|
| 696 |
+
from peft import PeftModel
|
| 697 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 698 |
+
|
| 699 |
+
run_root = _configured_root("A11OY_M1_RUN_ROOT")
|
| 700 |
+
base_root = _configured_root("A11OY_M1_BASE_SNAPSHOT")
|
| 701 |
+
if run_root is None or base_root is None:
|
| 702 |
+
raise RuntimeError("artifact roots unavailable")
|
| 703 |
+
adapter_root = _confined_file(run_root, "adapter/adapter_config.json").parent
|
| 704 |
+
gpu_index = int(os.environ.get("A11OY_M1_GPU_INDEX", "0"))
|
| 705 |
+
model = None
|
| 706 |
+
tuned = None
|
| 707 |
+
try:
|
| 708 |
+
torch.cuda.set_device(gpu_index)
|
| 709 |
+
tokenizer = AutoTokenizer.from_pretrained(str(adapter_root), local_files_only=True, trust_remote_code=False)
|
| 710 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 711 |
+
str(base_root), local_files_only=True, trust_remote_code=False, device_map={"": gpu_index}
|
| 712 |
+
)
|
| 713 |
+
tuned = PeftModel.from_pretrained(
|
| 714 |
+
model, str(adapter_root), local_files_only=True, is_trainable=False
|
| 715 |
+
)
|
| 716 |
+
tuned.eval()
|
| 717 |
+
inputs = tokenizer(parsed["prompt"], return_tensors="pt", truncation=True, max_length=384)
|
| 718 |
+
inputs = {key: value.to(f"cuda:{gpu_index}") for key, value in inputs.items()}
|
| 719 |
+
kwargs: dict[str, Any] = {
|
| 720 |
+
"max_new_tokens": parsed["max_new_tokens"], "use_cache": True,
|
| 721 |
+
"do_sample": parsed["temperature"] > 0,
|
| 722 |
+
}
|
| 723 |
+
if parsed["temperature"] > 0:
|
| 724 |
+
kwargs["temperature"] = parsed["temperature"]
|
| 725 |
+
with torch.inference_mode():
|
| 726 |
+
output = tuned.generate(**inputs, **kwargs)
|
| 727 |
+
new_tokens = output[0, inputs["input_ids"].shape[1]:]
|
| 728 |
+
text = tokenizer.decode(new_tokens, skip_special_tokens=True).strip()
|
| 729 |
+
if not text:
|
| 730 |
+
raise RuntimeError("local model returned no generated text")
|
| 731 |
+
return text
|
| 732 |
+
finally:
|
| 733 |
+
del tuned, model
|
| 734 |
+
gc.collect()
|
| 735 |
+
if torch.cuda.is_available():
|
| 736 |
+
torch.cuda.empty_cache()
|
| 737 |
+
|
| 738 |
+
|
| 739 |
+
def run_inference(payload: dict[str, Any]) -> tuple[dict[str, Any], int]:
|
| 740 |
+
try:
|
| 741 |
+
manifest = _load_manifest()
|
| 742 |
+
parsed = _parse_inference_request(payload, manifest)
|
| 743 |
+
except (OSError, ValueError, json.JSONDecodeError, KeyError, ContractError) as exc:
|
| 744 |
+
return {"schema": SCHEMA, "state": BLOCKED, "release_state": "NOT_PROMOTED",
|
| 745 |
+
"production_eligible": False, "error": str(exc)}, 422
|
| 746 |
+
|
| 747 |
+
status = operational_status()
|
| 748 |
+
if status["operational_state"] != READY:
|
| 749 |
+
code = 409 if status["operational_state"] == BLOCKED else 503
|
| 750 |
+
return {"schema": SCHEMA, "state": status["operational_state"], "release_state": "NOT_PROMOTED",
|
| 751 |
+
"production_eligible": False, "inference": None, "gate": status}, code
|
| 752 |
+
if not _INFERENCE_LOCK.acquire(blocking=False):
|
| 753 |
+
return {"schema": SCHEMA, "state": BLOCKED, "release_state": "NOT_PROMOTED",
|
| 754 |
+
"production_eligible": False, "error": "bounded M1 concurrency slot is busy"}, 429
|
| 755 |
+
started = time.perf_counter()
|
| 756 |
+
try:
|
| 757 |
+
# Re-run the full exact gate immediately before executing. No hash cache is
|
| 758 |
+
# used, so a changed file or GPU state fails closed.
|
| 759 |
+
preflight = operational_status()
|
| 760 |
+
if preflight["operational_state"] != READY:
|
| 761 |
+
code = 409 if preflight["operational_state"] == BLOCKED else 503
|
| 762 |
+
return {"schema": SCHEMA, "state": preflight["operational_state"],
|
| 763 |
+
"release_state": "NOT_PROMOTED", "production_eligible": False,
|
| 764 |
+
"inference": None, "gate": preflight}, code
|
| 765 |
+
try:
|
| 766 |
+
text = _local_peft_inference(parsed, manifest)
|
| 767 |
+
except Exception as exc:
|
| 768 |
+
return {"schema": SCHEMA, "state": UNAVAILABLE, "release_state": "NOT_PROMOTED",
|
| 769 |
+
"production_eligible": False, "inference": None,
|
| 770 |
+
"error": f"local inference failed ({type(exc).__name__}); no output fabricated"}, 503
|
| 771 |
+
receipt_core = {
|
| 772 |
+
"schema": RECEIPT_SCHEMA, "candidate_id": manifest["candidate_id"],
|
| 773 |
+
"release_state": "NOT_PROMOTED", "quality_claim": "NOT_ESTABLISHED",
|
| 774 |
+
"tier": "EXPERIMENTAL_LOCAL_ONLY", "provider_id": manifest["provider"]["id"],
|
| 775 |
+
"prompt_sha256": _digest_bytes(parsed["prompt"].encode("utf-8")),
|
| 776 |
+
"output_sha256": _digest_bytes(text.encode("utf-8")),
|
| 777 |
+
"max_new_tokens": parsed["max_new_tokens"], "temperature": parsed["temperature"],
|
| 778 |
+
"duration_ms": round((time.perf_counter() - started) * 1000, 3), "completed_at": _now(),
|
| 779 |
+
"network": "DISABLED", "production_eligible": False,
|
| 780 |
+
"corpus_receipt_id": preflight["checks"]["corpus_ingestion"]["corpus_receipt_id"],
|
| 781 |
+
"evaluation_receipt_id": preflight["checks"]["corpus_ingestion"]["evaluation_receipt_id"],
|
| 782 |
+
"corpus_relation": "PROPOSAL_ONLY_NOT_USED_BY_EXISTING_ADAPTER",
|
| 783 |
+
}
|
| 784 |
+
receipt = {**receipt_core, "receipt_sha256": _digest_bytes(_canonical(receipt_core)),
|
| 785 |
+
"signature_state": "UNSIGNED_DETERMINISTIC_DIGEST_ONLY"}
|
| 786 |
+
return {"schema": SCHEMA, "state": "RESULT", "release_state": "NOT_PROMOTED",
|
| 787 |
+
"quality_claim": "NOT_ESTABLISHED", "production_eligible": False,
|
| 788 |
+
"inference": {"text": text, "provider_id": manifest["provider"]["id"]},
|
| 789 |
+
"receipt": receipt}, 200
|
| 790 |
+
finally:
|
| 791 |
+
_INFERENCE_LOCK.release()
|
| 792 |
+
|
| 793 |
+
|
| 794 |
+
def register(app: Any, ns: str = "a11oy") -> dict[str, Any]:
|
| 795 |
+
from fastapi.responses import FileResponse, JSONResponse
|
| 796 |
+
|
| 797 |
+
prefix = f"/api/{ns}/v1/models/m1"
|
| 798 |
+
before = {id(route) for route in app.router.routes}
|
| 799 |
+
|
| 800 |
+
@app.get(prefix)
|
| 801 |
+
async def m1_status(): # noqa: ANN202
|
| 802 |
+
return JSONResponse(operational_status())
|
| 803 |
+
|
| 804 |
+
@app.post(f"{prefix}/infer")
|
| 805 |
+
async def m1_infer(request: Request): # noqa: ANN202
|
| 806 |
+
try:
|
| 807 |
+
manifest = _load_manifest()
|
| 808 |
+
payload = await _bounded_json(request, int(manifest["inference_policy"]["max_request_bytes"]))
|
| 809 |
+
except (ContractError, OSError, ValueError, json.JSONDecodeError, KeyError) as exc:
|
| 810 |
+
return JSONResponse({"schema": SCHEMA, "state": BLOCKED, "release_state": "NOT_PROMOTED",
|
| 811 |
+
"production_eligible": False, "error": str(exc)}, status_code=422)
|
| 812 |
+
result, status_code = await asyncio.to_thread(run_inference, payload)
|
| 813 |
+
return JSONResponse(result, status_code=status_code)
|
| 814 |
+
|
| 815 |
+
@app.get("/models/m1")
|
| 816 |
+
async def m1_page() -> Any:
|
| 817 |
+
if not PAGE_PATH.is_file():
|
| 818 |
+
return JSONResponse({"state": UNAVAILABLE, "error": "M1 status page is unavailable"}, status_code=503)
|
| 819 |
+
return FileResponse(PAGE_PATH, media_type="text/html")
|
| 820 |
+
|
| 821 |
+
added = [route for route in app.router.routes if id(route) not in before]
|
| 822 |
+
for route in added:
|
| 823 |
+
app.router.routes.remove(route)
|
| 824 |
+
for route in reversed(added):
|
| 825 |
+
app.router.routes.insert(0, route)
|
| 826 |
+
return {"registered": True, "routes": [prefix, f"{prefix}/infer", "/models/m1"],
|
| 827 |
+
"release_state": "NOT_PROMOTED", "production_eligible": False}
|
| 828 |
+
|
| 829 |
+
|
| 830 |
+
__all__ = [
|
| 831 |
+
"BLOCKED", "ContractError", "INFER_SCHEMA", "PASS", "READY", "SCHEMA",
|
| 832 |
+
"UNAVAILABLE", "operational_status", "register", "run_inference",
|
| 833 |
+
]
|
|
@@ -42,8 +42,8 @@ HONESTY (Doctrine v11 — NEVER violate)
|
|
| 42 |
ROADMAP inside the same payload (e.g. SZL-Nemo's on-box 2-GPU serving + Z3
|
| 43 |
cross-check for qhawaq + numpy-SIMD perf for waqay). We NEVER fake-LIVE a
|
| 44 |
capability that is not running, and we NEVER fabricate a metric.
|
| 45 |
-
* SZL-Nemo is a
|
| 46 |
-
|
| 47 |
Nemotron-Ultra, or any certification. The base/license are read straight from
|
| 48 |
a11oy_nemo_core.NEMO_BASE.
|
| 49 |
* locked theorems = EXACTLY 8 {F1,F4,F7,F11,F12,F18,F19,F22} @ kernel c7c0ba17
|
|
@@ -159,8 +159,8 @@ def _khipu_sign(surface: str, summary: dict) -> dict:
|
|
| 159 |
# /status BUILDERS — each reads ONLY the real backing module's live data.
|
| 160 |
# ===========================================================================
|
| 161 |
def _nemo_status() -> dict:
|
| 162 |
-
"""SZL-Nemo: governed
|
| 163 |
-
|
| 164 |
base = {}
|
| 165 |
experts: list = []
|
| 166 |
tiers: list = []
|
|
@@ -179,7 +179,8 @@ def _nemo_status() -> dict:
|
|
| 179 |
nemo_version = card.get("version")
|
| 180 |
except Exception as e: # noqa: BLE001
|
| 181 |
nemo_name, nemo_version = "SZL-Nemo", None
|
| 182 |
-
base = {"default_base": "
|
|
|
|
| 183 |
"_note": "a11oy_nemo_core not importable here (%r)" % e}
|
| 184 |
|
| 185 |
payload = {
|
|
@@ -189,23 +190,24 @@ def _nemo_status() -> dict:
|
|
| 189 |
"lifecycle": "LIVE",
|
| 190 |
"model": nemo_name,
|
| 191 |
"version": nemo_version,
|
| 192 |
-
"model_governed": "%s (governed)" % base.get("default_base", "
|
| 193 |
-
"base": base.get("default_base", "
|
| 194 |
-
"base_license": base.get("default_base_license", "
|
| 195 |
"base_url": base.get("default_base_url"),
|
| 196 |
-
"served_tier": "
|
| 197 |
-
"
|
| 198 |
-
"provenance": ("SZL-Nemo is
|
| 199 |
-
"
|
| 200 |
-
"
|
| 201 |
"what_is_live": [
|
| 202 |
"Λ-governed domain-expert MoE router (signed selection receipts) — LIVE",
|
| 203 |
"τ-bench self-improvement loop signing the measured delta — LIVE",
|
| 204 |
"model card / tiers / experts endpoints — LIVE",
|
|
|
|
| 205 |
],
|
| 206 |
"what_is_roadmap": [
|
| 207 |
-
"
|
| 208 |
-
"MTP / speculative decoding
|
| 209 |
],
|
| 210 |
"experts": experts,
|
| 211 |
"tiers": tiers,
|
|
@@ -537,8 +539,11 @@ def _selftest() -> dict:
|
|
| 537 |
out[name] = {"lifecycle": s["lifecycle"], "khipu_kind": s.get("khipu", {}).get("kind")}
|
| 538 |
# SZL-Nemo honesty: governed open base, never from-scratch.
|
| 539 |
n = _nemo_status()
|
| 540 |
-
assert n["base_license"]
|
| 541 |
-
|
|
|
|
|
|
|
|
|
|
| 542 |
out["nemo_base"] = (n["base"], n["base_license"])
|
| 543 |
# No banned codename leaks anywhere.
|
| 544 |
served = json.dumps(served_parts).lower()
|
|
|
|
| 42 |
ROADMAP inside the same payload (e.g. SZL-Nemo's on-box 2-GPU serving + Z3
|
| 43 |
cross-check for qhawaq + numpy-SIMD perf for waqay). We NEVER fake-LIVE a
|
| 44 |
capability that is not running, and we NEVER fabricate a metric.
|
| 45 |
+
* SZL-Nemo is a governed recipe built on NVIDIA Nemotron 3 Nano 4B. We NEVER
|
| 46 |
+
claim an SZL fine-tune, a from-scratch model, 550B params, a local
|
| 47 |
Nemotron-Ultra, or any certification. The base/license are read straight from
|
| 48 |
a11oy_nemo_core.NEMO_BASE.
|
| 49 |
* locked theorems = EXACTLY 8 {F1,F4,F7,F11,F12,F18,F19,F22} @ kernel c7c0ba17
|
|
|
|
| 159 |
# /status BUILDERS — each reads ONLY the real backing module's live data.
|
| 160 |
# ===========================================================================
|
| 161 |
def _nemo_status() -> dict:
|
| 162 |
+
"""SZL-Nemo: governed Nemotron 3 Nano 4B recipe. Router and runtime
|
| 163 |
+
readiness are reported independently; the recipe is not an SZL fine-tune."""
|
| 164 |
base = {}
|
| 165 |
experts: list = []
|
| 166 |
tiers: list = []
|
|
|
|
| 179 |
nemo_version = card.get("version")
|
| 180 |
except Exception as e: # noqa: BLE001
|
| 181 |
nemo_name, nemo_version = "SZL-Nemo", None
|
| 182 |
+
base = {"default_base": "NVIDIA Nemotron 3 Nano 4B",
|
| 183 |
+
"default_base_license": "NVIDIA Nemotron Open Model License",
|
| 184 |
"_note": "a11oy_nemo_core not importable here (%r)" % e}
|
| 185 |
|
| 186 |
payload = {
|
|
|
|
| 190 |
"lifecycle": "LIVE",
|
| 191 |
"model": nemo_name,
|
| 192 |
"version": nemo_version,
|
| 193 |
+
"model_governed": "%s (governed recipe)" % base.get("default_base", "UNKNOWN"),
|
| 194 |
+
"base": base.get("default_base", "UNKNOWN"),
|
| 195 |
+
"base_license": base.get("default_base_license", "UNKNOWN"),
|
| 196 |
"base_url": base.get("default_base_url"),
|
| 197 |
+
"served_tier": "exact-tag loopback Ollama runtime when identity-bound; "
|
| 198 |
+
"cloud-NIM tier remains sovereign:false",
|
| 199 |
+
"provenance": ("SZL-Nemo is the SZL governance/routing layer wrapped around "
|
| 200 |
+
"NVIDIA Nemotron 3 Nano 4B. The recipe is not an SZL fine-tune; "
|
| 201 |
+
"runtime readiness and model identity are separate evidence."),
|
| 202 |
"what_is_live": [
|
| 203 |
"Λ-governed domain-expert MoE router (signed selection receipts) — LIVE",
|
| 204 |
"τ-bench self-improvement loop signing the measured delta — LIVE",
|
| 205 |
"model card / tiers / experts endpoints — LIVE",
|
| 206 |
+
"exact upstream-manifest and derived-tag runtime probe — LIVE",
|
| 207 |
],
|
| 208 |
"what_is_roadmap": [
|
| 209 |
+
"Fine-tuned SZL-Nemo weights — NOT CREATED",
|
| 210 |
+
"MTP / speculative decoding — ROADMAP (not enabled on verified Ollama path)",
|
| 211 |
],
|
| 212 |
"experts": experts,
|
| 213 |
"tiers": tiers,
|
|
|
|
| 539 |
out[name] = {"lifecycle": s["lifecycle"], "khipu_kind": s.get("khipu", {}).get("kind")}
|
| 540 |
# SZL-Nemo honesty: governed open base, never from-scratch.
|
| 541 |
n = _nemo_status()
|
| 542 |
+
assert n["base_license"] == "NVIDIA Nemotron Open Model License", n["base_license"]
|
| 543 |
+
rendered = json.dumps(n).lower()
|
| 544 |
+
assert ("from-scratch" not in rendered
|
| 545 |
+
or "not an szl fine-tune" in rendered
|
| 546 |
+
or "did not train" in rendered)
|
| 547 |
out["nemo_base"] = (n["base"], n["base_license"])
|
| 548 |
# No banned codename leaks anywhere.
|
| 549 |
served = json.dumps(served_parts).lower()
|
|
@@ -0,0 +1,532 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Fail-closed external numerical-engine frontier.
|
| 3 |
+
|
| 4 |
+
The host accepts only three fixed numeric operations. It never accepts source
|
| 5 |
+
code, expressions, function names, file paths, packages, or shell arguments.
|
| 6 |
+
GNU Octave is an optional external process. MATLAB is an optional external
|
| 7 |
+
service executable with an offline-license status boundary; the proprietary
|
| 8 |
+
Python Engine is detected for status only and is never imported. Neither
|
| 9 |
+
engine, its libraries, nor its license material is shipped by a11oy.
|
| 10 |
+
|
| 11 |
+
External execution is allowed only on POSIX when ``unshare --net`` and resource
|
| 12 |
+
limits are available. The child runs with a private network namespace, a small
|
| 13 |
+
environment, a temporary working directory, and hard time/address-space/file-
|
| 14 |
+
size limits. Missing controls produce ``UNAVAILABLE`` rather than a soft
|
| 15 |
+
fallback. Results and receipts are deterministic hashes, always unsigned, and
|
| 16 |
+
never increase proof or trust state.
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
from __future__ import annotations
|
| 20 |
+
|
| 21 |
+
import hashlib
|
| 22 |
+
import importlib.util
|
| 23 |
+
import json
|
| 24 |
+
import math
|
| 25 |
+
import os
|
| 26 |
+
import re
|
| 27 |
+
import shutil
|
| 28 |
+
import subprocess
|
| 29 |
+
import tempfile
|
| 30 |
+
from pathlib import Path
|
| 31 |
+
from typing import Any, Callable, Mapping, Sequence
|
| 32 |
+
|
| 33 |
+
from starlette.requests import Request
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
REQUEST_SCHEMA = "szl.numerics.request/v1"
|
| 37 |
+
ENGINE_RESPONSE_SCHEMA = "szl.numerics.engine-response/v1"
|
| 38 |
+
RESULT_SCHEMA = "szl.numerics.result/v1"
|
| 39 |
+
COMPARE_SCHEMA = "szl.numerics.compare/v1"
|
| 40 |
+
RECEIPT_SCHEMA = "szl.numerics.receipt/v1"
|
| 41 |
+
OPERATIONS = ("MATRIX_SOLVE", "SYMMETRIC_EIGENVALUES", "VALIDATE_REFERENCE_VECTOR")
|
| 42 |
+
ENGINES = ("octave", "matlab")
|
| 43 |
+
MAX_BODY_BYTES = 128 * 1024
|
| 44 |
+
MAX_DIMENSION = 64
|
| 45 |
+
MAX_SCALARS = MAX_DIMENSION * MAX_DIMENSION + 2 * MAX_DIMENSION
|
| 46 |
+
MAX_ABS_VALUE = 1.0e12
|
| 47 |
+
MAX_TIMEOUT_SECONDS = 8
|
| 48 |
+
DEFAULT_TIMEOUT_SECONDS = 5
|
| 49 |
+
MAX_MEMORY_BYTES = 512 * 1024 * 1024
|
| 50 |
+
MAX_OUTPUT_BYTES = 256 * 1024
|
| 51 |
+
MAX_ABS_TOLERANCE = 1.0
|
| 52 |
+
MAX_REL_TOLERANCE = 1.0
|
| 53 |
+
ZERO_UPLIFT = {"proof_uplift": 0, "trust_uplift": 0}
|
| 54 |
+
_REQUEST_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$")
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class ContractError(ValueError):
|
| 58 |
+
"""The request or engine response violates the fixed contract."""
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
class EngineUnavailable(RuntimeError):
|
| 62 |
+
"""The external engine or a mandatory isolation control is unavailable."""
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def canonical_json(value: Any) -> bytes:
|
| 66 |
+
return json.dumps(
|
| 67 |
+
value,
|
| 68 |
+
sort_keys=True,
|
| 69 |
+
separators=(",", ":"),
|
| 70 |
+
ensure_ascii=False,
|
| 71 |
+
allow_nan=False,
|
| 72 |
+
).encode("utf-8")
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def digest_json(value: Any) -> str:
|
| 76 |
+
return hashlib.sha256(canonical_json(value)).hexdigest()
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def _mapping(value: Any, name: str) -> Mapping[str, Any]:
|
| 80 |
+
if not isinstance(value, Mapping):
|
| 81 |
+
raise ContractError(f"{name} must be an object")
|
| 82 |
+
return value
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def _strict_keys(value: Mapping[str, Any], allowed: set[str], name: str) -> None:
|
| 86 |
+
extras = sorted(set(value) - allowed)
|
| 87 |
+
missing = sorted(allowed - set(value))
|
| 88 |
+
if extras:
|
| 89 |
+
raise ContractError(f"{name} has unsupported fields: {', '.join(extras)}")
|
| 90 |
+
if missing:
|
| 91 |
+
raise ContractError(f"{name} is missing fields: {', '.join(missing)}")
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def _number(value: Any, name: str) -> float:
|
| 95 |
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
| 96 |
+
raise ContractError(f"{name} must be a finite JSON number")
|
| 97 |
+
result = float(value)
|
| 98 |
+
if not math.isfinite(result) or abs(result) > MAX_ABS_VALUE:
|
| 99 |
+
raise ContractError(f"{name} must be finite with absolute value <= {MAX_ABS_VALUE:g}")
|
| 100 |
+
return result
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def _vector(value: Any, name: str, length: int | None = None) -> list[float]:
|
| 104 |
+
if not isinstance(value, Sequence) or isinstance(value, (str, bytes, bytearray)):
|
| 105 |
+
raise ContractError(f"{name} must be an array")
|
| 106 |
+
if not value or len(value) > MAX_DIMENSION:
|
| 107 |
+
raise ContractError(f"{name} must contain 1..{MAX_DIMENSION} numbers")
|
| 108 |
+
if length is not None and len(value) != length:
|
| 109 |
+
raise ContractError(f"{name} must contain exactly {length} numbers")
|
| 110 |
+
return [_number(item, f"{name}[{index}]") for index, item in enumerate(value)]
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def _matrix(value: Any, name: str) -> list[list[float]]:
|
| 114 |
+
if not isinstance(value, Sequence) or isinstance(value, (str, bytes, bytearray)):
|
| 115 |
+
raise ContractError(f"{name} must be an array of rows")
|
| 116 |
+
if not value or len(value) > MAX_DIMENSION:
|
| 117 |
+
raise ContractError(f"{name} must contain 1..{MAX_DIMENSION} rows")
|
| 118 |
+
size = len(value)
|
| 119 |
+
rows = [_vector(row, f"{name}[{index}]", size) for index, row in enumerate(value)]
|
| 120 |
+
return rows
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def _tolerance(value: Any) -> dict[str, float]:
|
| 124 |
+
obj = _mapping(value, "tolerance")
|
| 125 |
+
_strict_keys(obj, {"absolute", "relative"}, "tolerance")
|
| 126 |
+
absolute = _number(obj["absolute"], "tolerance.absolute")
|
| 127 |
+
relative = _number(obj["relative"], "tolerance.relative")
|
| 128 |
+
if not 0.0 <= absolute <= MAX_ABS_TOLERANCE:
|
| 129 |
+
raise ContractError("tolerance.absolute must be between 0 and 1")
|
| 130 |
+
if not 0.0 <= relative <= MAX_REL_TOLERANCE:
|
| 131 |
+
raise ContractError("tolerance.relative must be between 0 and 1")
|
| 132 |
+
return {"absolute": absolute, "relative": relative}
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def parse_request(payload: Mapping[str, Any]) -> dict[str, Any]:
|
| 136 |
+
obj = _mapping(payload, "request")
|
| 137 |
+
_strict_keys(obj, {"schema", "request_id", "operation", "inputs", "tolerance"}, "request")
|
| 138 |
+
if obj["schema"] != REQUEST_SCHEMA:
|
| 139 |
+
raise ContractError(f"schema must be {REQUEST_SCHEMA}")
|
| 140 |
+
request_id = obj["request_id"]
|
| 141 |
+
if not isinstance(request_id, str) or not _REQUEST_ID_RE.fullmatch(request_id):
|
| 142 |
+
raise ContractError("request_id must match [A-Za-z0-9][A-Za-z0-9._:-]{0,63}")
|
| 143 |
+
operation = obj["operation"]
|
| 144 |
+
if operation not in OPERATIONS:
|
| 145 |
+
raise ContractError(f"operation must be one of: {', '.join(OPERATIONS)}")
|
| 146 |
+
raw_inputs = _mapping(obj["inputs"], "inputs")
|
| 147 |
+
if operation == "SYMMETRIC_EIGENVALUES":
|
| 148 |
+
_strict_keys(raw_inputs, {"matrix"}, "inputs")
|
| 149 |
+
elif operation == "MATRIX_SOLVE":
|
| 150 |
+
_strict_keys(raw_inputs, {"matrix", "rhs"}, "inputs")
|
| 151 |
+
else:
|
| 152 |
+
_strict_keys(raw_inputs, {"matrix", "rhs", "expected"}, "inputs")
|
| 153 |
+
|
| 154 |
+
matrix = _matrix(raw_inputs["matrix"], "inputs.matrix")
|
| 155 |
+
size = len(matrix)
|
| 156 |
+
inputs: dict[str, Any] = {"matrix": matrix}
|
| 157 |
+
if operation == "SYMMETRIC_EIGENVALUES":
|
| 158 |
+
for row in range(size):
|
| 159 |
+
for column in range(row + 1, size):
|
| 160 |
+
if abs(matrix[row][column] - matrix[column][row]) > 1.0e-12:
|
| 161 |
+
raise ContractError("SYMMETRIC_EIGENVALUES requires a symmetric matrix")
|
| 162 |
+
else:
|
| 163 |
+
inputs["rhs"] = _vector(raw_inputs["rhs"], "inputs.rhs", size)
|
| 164 |
+
if operation == "VALIDATE_REFERENCE_VECTOR":
|
| 165 |
+
inputs["expected"] = _vector(raw_inputs["expected"], "inputs.expected", size)
|
| 166 |
+
if sum(len(row) for row in matrix) + sum(
|
| 167 |
+
len(value) for value in inputs.values() if isinstance(value, list) and value and not isinstance(value[0], list)
|
| 168 |
+
) > MAX_SCALARS:
|
| 169 |
+
raise ContractError("request exceeds the scalar ceiling")
|
| 170 |
+
return {
|
| 171 |
+
"schema": REQUEST_SCHEMA,
|
| 172 |
+
"request_id": request_id,
|
| 173 |
+
"operation": operation,
|
| 174 |
+
"inputs": inputs,
|
| 175 |
+
"tolerance": _tolerance(obj["tolerance"]),
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def _configured_executable(name: str, env_key: str) -> str | None:
|
| 180 |
+
configured = os.environ.get(env_key, "").strip()
|
| 181 |
+
if configured:
|
| 182 |
+
path = Path(configured)
|
| 183 |
+
return str(path.resolve()) if path.is_absolute() and path.is_file() else None
|
| 184 |
+
discovered = shutil.which(name)
|
| 185 |
+
return str(Path(discovered).resolve()) if discovered else None
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
def _controls() -> dict[str, Any]:
|
| 189 |
+
try:
|
| 190 |
+
import resource # noqa: F401
|
| 191 |
+
resource_limits = os.name == "posix"
|
| 192 |
+
except ImportError:
|
| 193 |
+
resource_limits = False
|
| 194 |
+
unshare = shutil.which("unshare") if os.name == "posix" else None
|
| 195 |
+
return {
|
| 196 |
+
"network_isolation": "PRESENT_UNVERIFIED" if unshare else "SOURCE_UNAVAILABLE",
|
| 197 |
+
"network_launcher": str(Path(unshare).resolve()) if unshare else None,
|
| 198 |
+
"resource_limits": "PRESENT" if resource_limits else "SOURCE_UNAVAILABLE",
|
| 199 |
+
"memory_limit_bytes": MAX_MEMORY_BYTES,
|
| 200 |
+
"output_limit_bytes": MAX_OUTPUT_BYTES,
|
| 201 |
+
"timeout_limit_seconds": MAX_TIMEOUT_SECONDS,
|
| 202 |
+
"package_installs": "DISABLED",
|
| 203 |
+
"arbitrary_code": "DISABLED",
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def engine_status() -> dict[str, Any]:
|
| 208 |
+
controls = _controls()
|
| 209 |
+
controls_ready = bool(controls["network_launcher"] and controls["resource_limits"] == "PRESENT")
|
| 210 |
+
octave = _configured_executable("octave-cli", "A11OY_OCTAVE_EXECUTABLE")
|
| 211 |
+
matlab_service = _configured_executable("", "A11OY_MATLAB_SERVICE_EXECUTABLE")
|
| 212 |
+
# Looking up the top-level package is status-only and does not import it.
|
| 213 |
+
# Looking up ``matlab.engine`` could import its parent as a side effect.
|
| 214 |
+
matlab_engine = importlib.util.find_spec("matlab") is not None
|
| 215 |
+
matlab_offline_license = os.environ.get("A11OY_MATLAB_OFFLINE_LICENSE_CONFIGURED") == "1"
|
| 216 |
+
return {
|
| 217 |
+
"schema": "szl.numerics.status/v1",
|
| 218 |
+
"mode": "EXTERNAL_ENGINES_ONLY",
|
| 219 |
+
"substrate_evidence": "UNKNOWN",
|
| 220 |
+
"engines": {
|
| 221 |
+
"octave": {
|
| 222 |
+
"execution_state": "READY_TO_ATTEMPT" if octave and controls_ready else "UNAVAILABLE",
|
| 223 |
+
"executable": "PRESENT_UNVERIFIED" if octave else "SOURCE_UNAVAILABLE",
|
| 224 |
+
"executable_path": octave,
|
| 225 |
+
"license_boundary": "EXTERNAL_GPL_PROCESS_NOT_BUNDLED",
|
| 226 |
+
},
|
| 227 |
+
"matlab": {
|
| 228 |
+
"execution_state": "READY_TO_ATTEMPT" if matlab_service and matlab_offline_license and controls_ready else "UNAVAILABLE",
|
| 229 |
+
"service_executable": "PRESENT_UNVERIFIED" if matlab_service else "SOURCE_UNAVAILABLE",
|
| 230 |
+
"service_executable_path": matlab_service,
|
| 231 |
+
"python_engine_package": "PRESENT_STATUS_ONLY_NOT_IMPORTED" if matlab_engine else "SOURCE_UNAVAILABLE",
|
| 232 |
+
"offline_license_configuration": "CONFIGURED_UNVERIFIED" if matlab_offline_license else "SOURCE_UNAVAILABLE",
|
| 233 |
+
"license_boundary": "EXTERNAL_PROPRIETARY_SERVICE_NOT_BUNDLED",
|
| 234 |
+
},
|
| 235 |
+
},
|
| 236 |
+
"controls": controls,
|
| 237 |
+
"operations": list(OPERATIONS),
|
| 238 |
+
"limits": {
|
| 239 |
+
"max_body_bytes": MAX_BODY_BYTES,
|
| 240 |
+
"max_dimension": MAX_DIMENSION,
|
| 241 |
+
"max_scalars": MAX_SCALARS,
|
| 242 |
+
"max_abs_value": MAX_ABS_VALUE,
|
| 243 |
+
},
|
| 244 |
+
**ZERO_UPLIFT,
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
def _preexec_limits(timeout_seconds: int) -> Callable[[], None]:
|
| 249 |
+
def apply() -> None:
|
| 250 |
+
import resource
|
| 251 |
+
|
| 252 |
+
resource.setrlimit(resource.RLIMIT_AS, (MAX_MEMORY_BYTES, MAX_MEMORY_BYTES))
|
| 253 |
+
resource.setrlimit(resource.RLIMIT_CPU, (timeout_seconds, timeout_seconds))
|
| 254 |
+
resource.setrlimit(resource.RLIMIT_FSIZE, (MAX_OUTPUT_BYTES, MAX_OUTPUT_BYTES))
|
| 255 |
+
resource.setrlimit(resource.RLIMIT_NOFILE, (64, 64))
|
| 256 |
+
|
| 257 |
+
return apply
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
def _read_bounded(path: Path) -> bytes:
|
| 261 |
+
size = path.stat().st_size
|
| 262 |
+
if size > MAX_OUTPUT_BYTES:
|
| 263 |
+
raise EngineUnavailable("ENGINE_OUTPUT_LIMIT_EXCEEDED")
|
| 264 |
+
return path.read_bytes()
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
def _engine_command(engine: str, input_path: Path, output_path: Path) -> list[str]:
|
| 268 |
+
status = engine_status()
|
| 269 |
+
details = status["engines"][engine]
|
| 270 |
+
if details["execution_state"] != "READY_TO_ATTEMPT":
|
| 271 |
+
raise EngineUnavailable("ENGINE_OR_ISOLATION_CONTROL_UNAVAILABLE")
|
| 272 |
+
if engine == "octave":
|
| 273 |
+
script = Path(__file__).resolve().parent / "numerics" / "octave_adapter.m"
|
| 274 |
+
if not script.is_file():
|
| 275 |
+
raise EngineUnavailable("FIXED_OCTAVE_ADAPTER_SOURCE_UNAVAILABLE")
|
| 276 |
+
command = [details["executable_path"], "--quiet", "--no-gui", "--no-history", str(script), str(input_path), str(output_path)]
|
| 277 |
+
else:
|
| 278 |
+
command = [details["service_executable_path"], "--json-input", str(input_path), "--json-output", str(output_path)]
|
| 279 |
+
return [status["controls"]["network_launcher"], "--net", "--", *command]
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def _execute_external(engine: str, request: Mapping[str, Any], timeout_seconds: int) -> Mapping[str, Any]:
|
| 283 |
+
if engine not in ENGINES:
|
| 284 |
+
raise ContractError(f"engine must be one of: {', '.join(ENGINES)}")
|
| 285 |
+
if not 1 <= timeout_seconds <= MAX_TIMEOUT_SECONDS:
|
| 286 |
+
raise ContractError(f"timeout_seconds must be between 1 and {MAX_TIMEOUT_SECONDS}")
|
| 287 |
+
if os.name != "posix":
|
| 288 |
+
raise EngineUnavailable("POSIX_RESOURCE_AND_NETWORK_ISOLATION_UNAVAILABLE")
|
| 289 |
+
with tempfile.TemporaryDirectory(prefix="a11oy-numerics-") as tmp:
|
| 290 |
+
work = Path(tmp)
|
| 291 |
+
input_path = work / "request.json"
|
| 292 |
+
output_path = work / "response.json"
|
| 293 |
+
log_path = work / "engine.log"
|
| 294 |
+
input_path.write_bytes(canonical_json(request))
|
| 295 |
+
command = _engine_command(engine, input_path, output_path)
|
| 296 |
+
env = {
|
| 297 |
+
"HOME": str(work),
|
| 298 |
+
"TMPDIR": str(work),
|
| 299 |
+
"LANG": "C.UTF-8",
|
| 300 |
+
"LC_ALL": "C.UTF-8",
|
| 301 |
+
"OCTAVE_HISTFILE": os.devnull,
|
| 302 |
+
"PATH": "/usr/bin:/bin",
|
| 303 |
+
}
|
| 304 |
+
try:
|
| 305 |
+
with log_path.open("wb") as log:
|
| 306 |
+
completed = subprocess.run(
|
| 307 |
+
command,
|
| 308 |
+
cwd=work,
|
| 309 |
+
env=env,
|
| 310 |
+
stdin=subprocess.DEVNULL,
|
| 311 |
+
stdout=log,
|
| 312 |
+
stderr=subprocess.STDOUT,
|
| 313 |
+
shell=False,
|
| 314 |
+
timeout=timeout_seconds,
|
| 315 |
+
check=False,
|
| 316 |
+
preexec_fn=_preexec_limits(timeout_seconds),
|
| 317 |
+
)
|
| 318 |
+
except subprocess.TimeoutExpired as exc:
|
| 319 |
+
raise EngineUnavailable("ENGINE_TIMEOUT") from exc
|
| 320 |
+
except OSError as exc:
|
| 321 |
+
raise EngineUnavailable("ENGINE_START_FAILED") from exc
|
| 322 |
+
_read_bounded(log_path)
|
| 323 |
+
if completed.returncode != 0:
|
| 324 |
+
raise EngineUnavailable(f"ENGINE_EXIT_{completed.returncode}")
|
| 325 |
+
if not output_path.is_file():
|
| 326 |
+
raise EngineUnavailable("ENGINE_RESPONSE_UNAVAILABLE")
|
| 327 |
+
try:
|
| 328 |
+
response = json.loads(_read_bounded(output_path).decode("utf-8"))
|
| 329 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 330 |
+
raise EngineUnavailable("ENGINE_RESPONSE_INVALID_JSON") from exc
|
| 331 |
+
return _mapping(response, "engine response")
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
def _parse_engine_response(value: Mapping[str, Any], request: Mapping[str, Any]) -> list[float]:
|
| 335 |
+
obj = _mapping(value, "engine response")
|
| 336 |
+
_strict_keys(obj, {"schema", "state", "operation", "values", "substrate_evidence"}, "engine response")
|
| 337 |
+
if obj["schema"] != ENGINE_RESPONSE_SCHEMA or obj["state"] != "RESULT":
|
| 338 |
+
raise EngineUnavailable("ENGINE_RESPONSE_NOT_RESULT")
|
| 339 |
+
if obj["operation"] != request["operation"]:
|
| 340 |
+
raise EngineUnavailable("ENGINE_OPERATION_MISMATCH")
|
| 341 |
+
if obj["substrate_evidence"] not in ("MEASURED", "UNKNOWN"):
|
| 342 |
+
raise EngineUnavailable("ENGINE_SUBSTRATE_LABEL_INVALID")
|
| 343 |
+
values = _vector(obj["values"], "engine response.values", len(request["inputs"]["matrix"]))
|
| 344 |
+
return values
|
| 345 |
+
|
| 346 |
+
|
| 347 |
+
def _within(left: float, right: float, tolerance: Mapping[str, float]) -> bool:
|
| 348 |
+
return abs(left - right) <= tolerance["absolute"] + tolerance["relative"] * max(abs(left), abs(right))
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
def _receipt(kind: str, engine: str | None, request_digest: str, result: Mapping[str, Any]) -> dict[str, Any]:
|
| 352 |
+
body = {
|
| 353 |
+
"schema": RECEIPT_SCHEMA,
|
| 354 |
+
"kind": kind,
|
| 355 |
+
"engine": engine,
|
| 356 |
+
"request_sha256": request_digest,
|
| 357 |
+
"result_sha256": digest_json(result),
|
| 358 |
+
"signature_state": "UNSIGNED_DETERMINISTIC_DIGEST_ONLY",
|
| 359 |
+
**ZERO_UPLIFT,
|
| 360 |
+
}
|
| 361 |
+
return {**body, "receipt_sha256": digest_json(body)}
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
Executor = Callable[[Mapping[str, Any]], Mapping[str, Any]]
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
def run_engine(
|
| 368 |
+
engine: str,
|
| 369 |
+
payload: Mapping[str, Any],
|
| 370 |
+
*,
|
| 371 |
+
timeout_seconds: int = DEFAULT_TIMEOUT_SECONDS,
|
| 372 |
+
executor: Executor | None = None,
|
| 373 |
+
) -> dict[str, Any]:
|
| 374 |
+
if engine not in ENGINES:
|
| 375 |
+
raise ContractError(f"engine must be one of: {', '.join(ENGINES)}")
|
| 376 |
+
request = parse_request(payload)
|
| 377 |
+
request_digest = digest_json(request)
|
| 378 |
+
try:
|
| 379 |
+
raw = executor(request) if executor is not None else _execute_external(engine, request, timeout_seconds)
|
| 380 |
+
values = _parse_engine_response(raw, request)
|
| 381 |
+
reference = None
|
| 382 |
+
if request["operation"] == "VALIDATE_REFERENCE_VECTOR":
|
| 383 |
+
reference = "MATCH" if all(
|
| 384 |
+
_within(value, expected, request["tolerance"])
|
| 385 |
+
for value, expected in zip(values, request["inputs"]["expected"])
|
| 386 |
+
) else "CONFLICT"
|
| 387 |
+
core = {
|
| 388 |
+
"schema": RESULT_SCHEMA,
|
| 389 |
+
"state": "RESULT",
|
| 390 |
+
"engine": engine,
|
| 391 |
+
"request_id": request["request_id"],
|
| 392 |
+
"request_sha256": request_digest,
|
| 393 |
+
"operation": request["operation"],
|
| 394 |
+
"values": values,
|
| 395 |
+
"reference_validation": reference,
|
| 396 |
+
"substrate_evidence": "UNKNOWN",
|
| 397 |
+
"signature_state": "UNSIGNED",
|
| 398 |
+
**ZERO_UPLIFT,
|
| 399 |
+
}
|
| 400 |
+
except EngineUnavailable as exc:
|
| 401 |
+
core = {
|
| 402 |
+
"schema": RESULT_SCHEMA,
|
| 403 |
+
"state": "UNAVAILABLE",
|
| 404 |
+
"engine": engine,
|
| 405 |
+
"request_id": request["request_id"],
|
| 406 |
+
"request_sha256": request_digest,
|
| 407 |
+
"operation": request["operation"],
|
| 408 |
+
"reason": str(exc),
|
| 409 |
+
"substrate_evidence": "UNKNOWN",
|
| 410 |
+
"signature_state": "UNSIGNED",
|
| 411 |
+
**ZERO_UPLIFT,
|
| 412 |
+
}
|
| 413 |
+
return {**core, "receipt": _receipt("ENGINE_RUN", engine, request_digest, core)}
|
| 414 |
+
|
| 415 |
+
|
| 416 |
+
def compare_engines(
|
| 417 |
+
payload: Mapping[str, Any],
|
| 418 |
+
*,
|
| 419 |
+
executors: Mapping[str, Executor] | None = None,
|
| 420 |
+
) -> dict[str, Any]:
|
| 421 |
+
request = parse_request(payload)
|
| 422 |
+
request_digest = digest_json(request)
|
| 423 |
+
configured = executors or {}
|
| 424 |
+
results = {
|
| 425 |
+
engine: run_engine(engine, request, executor=configured.get(engine))
|
| 426 |
+
for engine in ENGINES
|
| 427 |
+
}
|
| 428 |
+
if any(result["state"] != "RESULT" for result in results.values()):
|
| 429 |
+
state = "UNAVAILABLE"
|
| 430 |
+
metrics = None
|
| 431 |
+
else:
|
| 432 |
+
octave_values = results["octave"]["values"]
|
| 433 |
+
matlab_values = results["matlab"]["values"]
|
| 434 |
+
differences = [abs(left - right) for left, right in zip(octave_values, matlab_values)]
|
| 435 |
+
state = "MATCH" if all(
|
| 436 |
+
_within(left, right, request["tolerance"])
|
| 437 |
+
for left, right in zip(octave_values, matlab_values)
|
| 438 |
+
) else "CONFLICT"
|
| 439 |
+
metrics = {
|
| 440 |
+
"max_absolute_difference": max(differences, default=0.0),
|
| 441 |
+
"declared_tolerance": request["tolerance"],
|
| 442 |
+
}
|
| 443 |
+
core = {
|
| 444 |
+
"schema": COMPARE_SCHEMA,
|
| 445 |
+
"comparison_state": state,
|
| 446 |
+
"request_id": request["request_id"],
|
| 447 |
+
"request_sha256": request_digest,
|
| 448 |
+
"operation": request["operation"],
|
| 449 |
+
"engine_states": {engine: result["state"] for engine, result in results.items()},
|
| 450 |
+
"engine_result_sha256": {engine: result["receipt"]["result_sha256"] for engine, result in results.items()},
|
| 451 |
+
"metrics": metrics,
|
| 452 |
+
"substrate_evidence": "UNKNOWN",
|
| 453 |
+
"signature_state": "UNSIGNED",
|
| 454 |
+
**ZERO_UPLIFT,
|
| 455 |
+
}
|
| 456 |
+
return {**core, "receipt": _receipt("CROSS_ENGINE_COMPARE", None, request_digest, core)}
|
| 457 |
+
|
| 458 |
+
|
| 459 |
+
async def _bounded_json_body(request: Any) -> dict[str, Any]:
|
| 460 |
+
declared = request.headers.get("content-length")
|
| 461 |
+
if declared is not None:
|
| 462 |
+
try:
|
| 463 |
+
size = int(declared)
|
| 464 |
+
except ValueError as exc:
|
| 465 |
+
raise ContractError("content-length must be a non-negative integer") from exc
|
| 466 |
+
if size < 0:
|
| 467 |
+
raise ContractError("content-length must be a non-negative integer")
|
| 468 |
+
if size > MAX_BODY_BYTES:
|
| 469 |
+
raise ContractError("request body exceeds 128 KiB")
|
| 470 |
+
data = bytearray()
|
| 471 |
+
async for chunk in request.stream():
|
| 472 |
+
if len(data) + len(chunk) > MAX_BODY_BYTES:
|
| 473 |
+
raise ContractError("request body exceeds 128 KiB")
|
| 474 |
+
data.extend(chunk)
|
| 475 |
+
try:
|
| 476 |
+
value = json.loads(bytes(data).decode("utf-8"))
|
| 477 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 478 |
+
raise ContractError("request body must be one JSON object") from exc
|
| 479 |
+
if not isinstance(value, dict):
|
| 480 |
+
raise ContractError("request body must be one JSON object")
|
| 481 |
+
return value
|
| 482 |
+
|
| 483 |
+
|
| 484 |
+
def register(app: Any, ns: str = "a11oy") -> dict[str, Any]:
|
| 485 |
+
"""Register the fixed status/run/compare routes on a FastAPI application."""
|
| 486 |
+
|
| 487 |
+
from fastapi.responses import JSONResponse
|
| 488 |
+
|
| 489 |
+
prefix = f"/api/{ns}/v1/numerics"
|
| 490 |
+
|
| 491 |
+
@app.get(f"{prefix}/status")
|
| 492 |
+
async def numerics_status(): # noqa: ANN202
|
| 493 |
+
return JSONResponse(engine_status())
|
| 494 |
+
|
| 495 |
+
@app.post(f"{prefix}/run/{{engine}}")
|
| 496 |
+
async def numerics_run(engine: str, request: Request): # noqa: ANN202
|
| 497 |
+
try:
|
| 498 |
+
result = run_engine(engine, await _bounded_json_body(request))
|
| 499 |
+
except ContractError as exc:
|
| 500 |
+
return JSONResponse({"state": "REJECTED", "error": str(exc), "substrate_evidence": "UNKNOWN", **ZERO_UPLIFT}, status_code=422)
|
| 501 |
+
return JSONResponse(result, status_code=200 if result["state"] == "RESULT" else 503)
|
| 502 |
+
|
| 503 |
+
@app.post(f"{prefix}/compare")
|
| 504 |
+
async def numerics_compare(request: Request): # noqa: ANN202
|
| 505 |
+
try:
|
| 506 |
+
result = compare_engines(await _bounded_json_body(request))
|
| 507 |
+
except ContractError as exc:
|
| 508 |
+
return JSONResponse({"comparison_state": "REJECTED", "error": str(exc), "substrate_evidence": "UNKNOWN", **ZERO_UPLIFT}, status_code=422)
|
| 509 |
+
return JSONResponse(result, status_code=200 if result["comparison_state"] in ("MATCH", "CONFLICT") else 503)
|
| 510 |
+
|
| 511 |
+
return {
|
| 512 |
+
"registered": True,
|
| 513 |
+
"routes": [f"{prefix}/status", f"{prefix}/run/{{engine}}", f"{prefix}/compare"],
|
| 514 |
+
"engines_bundled": 0,
|
| 515 |
+
**ZERO_UPLIFT,
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
__all__ = [
|
| 520 |
+
"COMPARE_SCHEMA",
|
| 521 |
+
"ContractError",
|
| 522 |
+
"ENGINE_RESPONSE_SCHEMA",
|
| 523 |
+
"ENGINES",
|
| 524 |
+
"OPERATIONS",
|
| 525 |
+
"REQUEST_SCHEMA",
|
| 526 |
+
"compare_engines",
|
| 527 |
+
"digest_json",
|
| 528 |
+
"engine_status",
|
| 529 |
+
"parse_request",
|
| 530 |
+
"register",
|
| 531 |
+
"run_engine",
|
| 532 |
+
]
|
|
@@ -0,0 +1,1000 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Deterministic, evidence-typed numerical evaluator dataset service.
|
| 3 |
+
|
| 4 |
+
Taxonomy home: services/numerics. This module freezes and serves the
|
| 5 |
+
preregistered matrix-case design, accepts only authenticated bounded run
|
| 6 |
+
receipts, computes binary64 diagnostics, and appends an integrity-linked row to
|
| 7 |
+
an NDJSON ledger. It does not invoke MATLAB or Octave, does not infer engine or
|
| 8 |
+
network availability, and never increases proof or trust state.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import datetime as _datetime
|
| 12 |
+
import hashlib
|
| 13 |
+
import hmac
|
| 14 |
+
import json
|
| 15 |
+
import math
|
| 16 |
+
import os
|
| 17 |
+
import re
|
| 18 |
+
import threading
|
| 19 |
+
from functools import lru_cache
|
| 20 |
+
from pathlib import Path
|
| 21 |
+
from typing import Any, Iterable, Mapping, Sequence
|
| 22 |
+
|
| 23 |
+
import szl_numerics_adapter as _adapter
|
| 24 |
+
import szl_puriq_formulas as _puriq
|
| 25 |
+
from starlette.requests import Request
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
PREREGISTRATION_SCHEMA = "szl.numerics.dataset-preregistration/v1"
|
| 29 |
+
INGEST_SCHEMA = "szl.numerics.dataset-ingest/v1"
|
| 30 |
+
CASE_SCHEMA = "szl.numerics.dataset-case/v1"
|
| 31 |
+
ROW_SCHEMA = "szl.numerics.dataset-row/v1"
|
| 32 |
+
STATUS_SCHEMA = "szl.numerics.dataset-status/v1"
|
| 33 |
+
CURRICULUM_SCHEMA = "szl.numerics.formula-curriculum/v1"
|
| 34 |
+
MAX_LEDGER_ROWS = 10_000
|
| 35 |
+
MAX_LEDGER_BYTES = 64 * 1024 * 1024
|
| 36 |
+
MAX_ROW_BYTES = 64 * 1024
|
| 37 |
+
MAX_PAGE_SIZE = 100
|
| 38 |
+
ZERO_UPLIFT = {"proof_uplift": 0, "trust_uplift": 0}
|
| 39 |
+
_ROOT = Path(__file__).resolve().parent
|
| 40 |
+
_MANIFEST_PATH = _ROOT / "numerics" / "dataset_preregistration.json"
|
| 41 |
+
_FORMULA_SOURCE_PATH = _ROOT / "szl_puriq_formulas.py"
|
| 42 |
+
_LICENSE_PATH = _ROOT / "LICENSE"
|
| 43 |
+
_LOCKED_FORMULA_IDS = frozenset({"F1", "F4", "F7", "F11", "F12", "F18", "F19", "F22"})
|
| 44 |
+
_SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
|
| 45 |
+
_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,95}$")
|
| 46 |
+
_CASE_RE = re.compile(r"^case-[a-z0-9-]{8,120}$")
|
| 47 |
+
_LEDGER_LOCK = threading.Lock()
|
| 48 |
+
_MASK64 = (1 << 64) - 1
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
class DatasetContractError(ValueError):
|
| 52 |
+
"""A case selector or ingested row violates the frozen contract."""
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class DatasetUnavailable(RuntimeError):
|
| 56 |
+
"""A mandatory dataset service precondition is unavailable."""
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def _file_sha256(path: Path) -> str:
|
| 60 |
+
digest = hashlib.sha256()
|
| 61 |
+
with path.open("rb") as handle:
|
| 62 |
+
for block in iter(lambda: handle.read(1024 * 1024), b""):
|
| 63 |
+
digest.update(block)
|
| 64 |
+
return digest.hexdigest()
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def _formula_source_family(meta: Mapping[str, Any]) -> str:
|
| 68 |
+
organ = str(meta.get("organ") or "source-unavailable").strip().lower()
|
| 69 |
+
organ = re.sub(r"[^a-z0-9]+", "-", organ).strip("-") or "source-unavailable"
|
| 70 |
+
return f"puriq-formula-meta/{organ}"
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def _source_family_split(source_family: str) -> str:
|
| 74 |
+
"""Assign a whole source family to one split to prevent family leakage."""
|
| 75 |
+
|
| 76 |
+
bucket = int(hashlib.sha256(source_family.encode("utf-8")).hexdigest()[:8], 16) % 10
|
| 77 |
+
if bucket < 7:
|
| 78 |
+
return "train"
|
| 79 |
+
if bucket < 9:
|
| 80 |
+
return "validation"
|
| 81 |
+
return "test"
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
@lru_cache(maxsize=1)
|
| 85 |
+
def formula_curriculum() -> dict[str, Any]:
|
| 86 |
+
"""Build the full formula-ID/status curriculum without manufacturing proof evidence.
|
| 87 |
+
|
| 88 |
+
This is a metadata bridge into the Brain curriculum, not a theorem dataset.
|
| 89 |
+
The local canonical registry and repository license are content-addressed. A
|
| 90 |
+
proof/refutation receipt remains null unless an exact per-formula receipt is
|
| 91 |
+
present; the repository currently provides no such mapping.
|
| 92 |
+
"""
|
| 93 |
+
|
| 94 |
+
if not _FORMULA_SOURCE_PATH.is_file() or not _LICENSE_PATH.is_file():
|
| 95 |
+
raise DatasetUnavailable("FORMULA_CURRICULUM_SOURCE_OR_LICENSE_UNAVAILABLE")
|
| 96 |
+
source_sha256 = _file_sha256(_FORMULA_SOURCE_PATH)
|
| 97 |
+
license_sha256 = _file_sha256(_LICENSE_PATH)
|
| 98 |
+
eligible: list[dict[str, Any]] = []
|
| 99 |
+
quarantined: list[dict[str, Any]] = []
|
| 100 |
+
expected_ids = {f"F{index}" for index in range(1, 24)}
|
| 101 |
+
|
| 102 |
+
def quarantine(formula_id: str, reasons: Sequence[str], meta: Mapping[str, Any] | None = None) -> None:
|
| 103 |
+
quarantined.append({
|
| 104 |
+
"formula_id": formula_id,
|
| 105 |
+
"reasons": sorted(set(reasons)),
|
| 106 |
+
"source_record_sha256": _adapter.digest_json(dict(meta)) if meta is not None else None,
|
| 107 |
+
"proof_receipt_sha256": None,
|
| 108 |
+
"refutation_receipt_sha256": None,
|
| 109 |
+
"proof_uplift": 0,
|
| 110 |
+
"trust_uplift": 0,
|
| 111 |
+
})
|
| 112 |
+
|
| 113 |
+
for formula_id in sorted(expected_ids, key=lambda token: int(token[1:])):
|
| 114 |
+
meta = _puriq.FORMULA_META.get(formula_id)
|
| 115 |
+
if not isinstance(meta, Mapping):
|
| 116 |
+
quarantine(formula_id, ["CANONICAL_RECORD_UNAVAILABLE"])
|
| 117 |
+
continue
|
| 118 |
+
reasons: list[str] = []
|
| 119 |
+
if meta.get("id") != formula_id:
|
| 120 |
+
reasons.append("FORMULA_ID_CONFLICT")
|
| 121 |
+
status = meta.get("proof_status")
|
| 122 |
+
if status not in {"PROVED", "UNATTEMPTED", "CONJECTURE_1"}:
|
| 123 |
+
reasons.append("UNSUPPORTED_PROOF_STATUS")
|
| 124 |
+
if (formula_id in _LOCKED_FORMULA_IDS) != (status == "PROVED"):
|
| 125 |
+
reasons.append("LOCKED_PROOF_CLAIM_CONFLICT")
|
| 126 |
+
if formula_id == "F23" and status != "CONJECTURE_1":
|
| 127 |
+
reasons.append("LAMBDA_CONJECTURE_STATUS_CONFLICT")
|
| 128 |
+
required_text = ("name", "organ", "primitive", "identity_doc")
|
| 129 |
+
if any(not isinstance(meta.get(field), str) or not str(meta[field]).strip() for field in required_text):
|
| 130 |
+
reasons.append("PROVENANCE_METADATA_INCOMPLETE")
|
| 131 |
+
if reasons:
|
| 132 |
+
quarantine(formula_id, reasons, meta)
|
| 133 |
+
continue
|
| 134 |
+
|
| 135 |
+
source_family = _formula_source_family(meta)
|
| 136 |
+
proof_note = meta.get("proof_note")
|
| 137 |
+
if status == "PROVED" and proof_note:
|
| 138 |
+
claim_scope = "LOCKED_THEOREM_ONLY_FORMULA_IDENTITY_SCOPE_MAY_DIFFER"
|
| 139 |
+
elif status == "PROVED":
|
| 140 |
+
claim_scope = "LOCKED_THEOREM_REPORTED_BY_CANONICAL_REGISTRY"
|
| 141 |
+
elif status == "CONJECTURE_1":
|
| 142 |
+
claim_scope = "CONJECTURE_1_OPEN_NOT_A_THEOREM"
|
| 143 |
+
else:
|
| 144 |
+
claim_scope = "OPEN_PROOF_OBLIGATION_UNATTEMPTED"
|
| 145 |
+
eligible.append({
|
| 146 |
+
"formula_id": formula_id,
|
| 147 |
+
"name": meta["name"],
|
| 148 |
+
"organ": meta["organ"],
|
| 149 |
+
"primitive": meta["primitive"],
|
| 150 |
+
"identity_doc": meta["identity_doc"],
|
| 151 |
+
"proof_status": status,
|
| 152 |
+
"lean_name": meta.get("lean_name"),
|
| 153 |
+
"lean_status": meta.get("lean_status"),
|
| 154 |
+
"locked": formula_id in _LOCKED_FORMULA_IDS,
|
| 155 |
+
"claim_scope": claim_scope,
|
| 156 |
+
"source_family": source_family,
|
| 157 |
+
"split": _source_family_split(source_family),
|
| 158 |
+
"source_record_sha256": _adapter.digest_json(dict(meta)),
|
| 159 |
+
"proof_receipt_sha256": None,
|
| 160 |
+
"refutation_receipt_sha256": None,
|
| 161 |
+
"receipt_state": "PER_FORMULA_RECEIPT_SOURCE_UNAVAILABLE",
|
| 162 |
+
"license_state": "REPOSITORY_APACHE_2_0",
|
| 163 |
+
"dataset_role": "STATUS_AND_PROVENANCE_METADATA_ONLY",
|
| 164 |
+
"proof_uplift": 0,
|
| 165 |
+
"trust_uplift": 0,
|
| 166 |
+
})
|
| 167 |
+
|
| 168 |
+
extras = sorted(set(_puriq.FORMULA_META) - expected_ids)
|
| 169 |
+
for formula_id in extras:
|
| 170 |
+
meta = _puriq.FORMULA_META[formula_id]
|
| 171 |
+
quarantine(str(formula_id), ["FORMULA_ID_OUTSIDE_F1_F23_CONTRACT"], meta if isinstance(meta, Mapping) else None)
|
| 172 |
+
|
| 173 |
+
split_families: dict[str, list[str]] = {"train": [], "validation": [], "test": []}
|
| 174 |
+
for item in eligible:
|
| 175 |
+
if item["source_family"] not in split_families[item["split"]]:
|
| 176 |
+
split_families[item["split"]].append(item["source_family"])
|
| 177 |
+
for families in split_families.values():
|
| 178 |
+
families.sort()
|
| 179 |
+
return {
|
| 180 |
+
"schema": CURRICULUM_SCHEMA,
|
| 181 |
+
"state": "READY" if eligible and not quarantined else ("PARTIAL" if eligible else "UNAVAILABLE"),
|
| 182 |
+
"dataset_role": "BRAIN_CURRICULUM_FORMULA_STATUS_AND_PROVENANCE_METADATA",
|
| 183 |
+
"canonical_source": {
|
| 184 |
+
"path": "szl_puriq_formulas.py",
|
| 185 |
+
"sha256": source_sha256,
|
| 186 |
+
"license": "Apache-2.0",
|
| 187 |
+
"license_file_sha256": license_sha256,
|
| 188 |
+
},
|
| 189 |
+
"formula_contract": {
|
| 190 |
+
"expected_ids": [f"F{index}" for index in range(1, 24)],
|
| 191 |
+
"locked_proven_ids": sorted(_LOCKED_FORMULA_IDS, key=lambda token: int(token[1:])),
|
| 192 |
+
"lambda_formula_id": "F23",
|
| 193 |
+
"lambda_status": "CONJECTURE_1",
|
| 194 |
+
},
|
| 195 |
+
"counts": {
|
| 196 |
+
"expected": 23,
|
| 197 |
+
"eligible": len(eligible),
|
| 198 |
+
"quarantined": len(quarantined),
|
| 199 |
+
"source_families": len({item["source_family"] for item in eligible}),
|
| 200 |
+
},
|
| 201 |
+
"source_family_split": {
|
| 202 |
+
"method": "SHA256_FAMILY_BUCKET_70_20_10_NO_FAMILY_LEAKAGE",
|
| 203 |
+
"families": split_families,
|
| 204 |
+
},
|
| 205 |
+
"eligible": eligible,
|
| 206 |
+
"quarantined": quarantined,
|
| 207 |
+
"receipt_boundary": (
|
| 208 |
+
"Null receipt hashes mean no exact per-formula proof/refutation receipt mapping was found; "
|
| 209 |
+
"canonical registry status is not upgraded into receipt evidence."
|
| 210 |
+
),
|
| 211 |
+
"interpretation_guard": (
|
| 212 |
+
"This curriculum carries formula identifiers, statuses, and provenance metadata only. "
|
| 213 |
+
"It does not prove formulas, refute conjectures, or improve numerical-result trust."
|
| 214 |
+
),
|
| 215 |
+
**ZERO_UPLIFT,
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
def _strict(value: Any, required: set[str], name: str) -> Mapping[str, Any]:
|
| 220 |
+
if not isinstance(value, Mapping):
|
| 221 |
+
raise DatasetContractError(f"{name} must be an object")
|
| 222 |
+
missing = sorted(required - set(value))
|
| 223 |
+
extras = sorted(set(value) - required)
|
| 224 |
+
if missing:
|
| 225 |
+
raise DatasetContractError(f"{name} is missing fields: {', '.join(missing)}")
|
| 226 |
+
if extras:
|
| 227 |
+
raise DatasetContractError(f"{name} has unsupported fields: {', '.join(extras)}")
|
| 228 |
+
return value
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
def _finite(value: Any, name: str) -> float:
|
| 232 |
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
| 233 |
+
raise DatasetContractError(f"{name} must be a finite JSON number")
|
| 234 |
+
result = float(value)
|
| 235 |
+
if not math.isfinite(result) or abs(result) > _adapter.MAX_ABS_VALUE:
|
| 236 |
+
raise DatasetContractError(f"{name} must be finite and bounded")
|
| 237 |
+
return result
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
def _nullable_uint(value: Any, name: str) -> int | None:
|
| 241 |
+
if value is None:
|
| 242 |
+
return None
|
| 243 |
+
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
|
| 244 |
+
raise DatasetContractError(f"{name} must be a non-negative integer or null")
|
| 245 |
+
return value
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
def _sha_or_none(value: Any, name: str) -> str | None:
|
| 249 |
+
if value is None:
|
| 250 |
+
return None
|
| 251 |
+
if not isinstance(value, str) or not _SHA256_RE.fullmatch(value):
|
| 252 |
+
raise DatasetContractError(f"{name} must be a lowercase SHA-256 digest or null")
|
| 253 |
+
return value
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
def _utc_timestamp(value: Any) -> str:
|
| 257 |
+
if not isinstance(value, str) or len(value) > 40:
|
| 258 |
+
raise DatasetContractError("observed_at_utc must be an ISO-8601 timestamp")
|
| 259 |
+
try:
|
| 260 |
+
parsed = _datetime.datetime.fromisoformat(value.replace("Z", "+00:00"))
|
| 261 |
+
except ValueError as exc:
|
| 262 |
+
raise DatasetContractError("observed_at_utc must be an ISO-8601 timestamp") from exc
|
| 263 |
+
if parsed.tzinfo is None or parsed.utcoffset() is None:
|
| 264 |
+
raise DatasetContractError("observed_at_utc must include a UTC offset")
|
| 265 |
+
return parsed.astimezone(_datetime.timezone.utc).isoformat().replace("+00:00", "Z")
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
@lru_cache(maxsize=1)
|
| 269 |
+
def preregistration() -> dict[str, Any]:
|
| 270 |
+
try:
|
| 271 |
+
value = json.loads(_MANIFEST_PATH.read_text(encoding="utf-8"))
|
| 272 |
+
except (OSError, json.JSONDecodeError) as exc:
|
| 273 |
+
raise DatasetUnavailable("PREREGISTRATION_SOURCE_UNAVAILABLE") from exc
|
| 274 |
+
required = {
|
| 275 |
+
"schema", "protocol_id", "protocol_version", "state", "frozen_before_execution",
|
| 276 |
+
"results_present", "matrix_dimensions", "deterministic_seeds",
|
| 277 |
+
"condition_number_strata", "confirmatory_matrix_families",
|
| 278 |
+
"exploratory_matrix_families", "fixture_generation", "tolerance",
|
| 279 |
+
"machine_epsilon_binary64", "execution_order_seed", "engines",
|
| 280 |
+
"expected_case_counts", "evidence_boundary",
|
| 281 |
+
}
|
| 282 |
+
_strict(value, required, "preregistration")
|
| 283 |
+
if value["schema"] != PREREGISTRATION_SCHEMA:
|
| 284 |
+
raise DatasetUnavailable("PREREGISTRATION_SCHEMA_MISMATCH")
|
| 285 |
+
if value["matrix_dimensions"] != [2, 4, 8, 16, 32, 64]:
|
| 286 |
+
raise DatasetUnavailable("PREREGISTRATION_DIMENSIONS_MISMATCH")
|
| 287 |
+
if value["deterministic_seeds"] != [1729, 57721, 271828, 314159, 1618033]:
|
| 288 |
+
raise DatasetUnavailable("PREREGISTRATION_SEEDS_MISMATCH")
|
| 289 |
+
if value["expected_case_counts"] != {"confirmatory": 1320, "exploratory": 8, "total": 1328}:
|
| 290 |
+
raise DatasetUnavailable("PREREGISTRATION_CASE_COUNT_MISMATCH")
|
| 291 |
+
if value["engines"] != ["octave", "matlab"]:
|
| 292 |
+
raise DatasetUnavailable("PREREGISTRATION_ENGINE_SET_MISMATCH")
|
| 293 |
+
return value
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
class _SplitMix64:
|
| 297 |
+
def __init__(self, seed: int) -> None:
|
| 298 |
+
self.state = seed & _MASK64
|
| 299 |
+
|
| 300 |
+
def next_u64(self) -> int:
|
| 301 |
+
self.state = (self.state + 0x9E3779B97F4A7C15) & _MASK64
|
| 302 |
+
z = self.state
|
| 303 |
+
z = ((z ^ (z >> 30)) * 0xBF58476D1CE4E5B9) & _MASK64
|
| 304 |
+
z = ((z ^ (z >> 27)) * 0x94D049BB133111EB) & _MASK64
|
| 305 |
+
return (z ^ (z >> 31)) & _MASK64
|
| 306 |
+
|
| 307 |
+
def uniform(self) -> float:
|
| 308 |
+
return (self.next_u64() >> 11) / float(1 << 53)
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
def _derived_seed(seed: int, family: str, label: str) -> int:
|
| 312 |
+
payload = f"szl-numerics-v1:{seed}:{family}:{label}".encode("ascii")
|
| 313 |
+
return int.from_bytes(hashlib.sha256(payload).digest()[:8], "big")
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
def _identity(n: int) -> list[list[float]]:
|
| 317 |
+
return [[1.0 if row == column else 0.0 for column in range(n)] for row in range(n)]
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
def _orthogonal(n: int, seed: int) -> list[list[float]]:
|
| 321 |
+
generator = _SplitMix64(seed)
|
| 322 |
+
result = _identity(n)
|
| 323 |
+
for left in range(n):
|
| 324 |
+
for right in range(left + 1, n):
|
| 325 |
+
theta = 2.0 * math.pi * generator.uniform()
|
| 326 |
+
cosine, sine = math.cos(theta), math.sin(theta)
|
| 327 |
+
for row in range(n):
|
| 328 |
+
old_left, old_right = result[row][left], result[row][right]
|
| 329 |
+
result[row][left] = cosine * old_left - sine * old_right
|
| 330 |
+
result[row][right] = sine * old_left + cosine * old_right
|
| 331 |
+
return result
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
def _spectrum(n: int, kappa: float, *, signed: bool = False) -> list[float]:
|
| 335 |
+
if n == 1:
|
| 336 |
+
values = [1.0]
|
| 337 |
+
else:
|
| 338 |
+
exponent = math.log10(kappa)
|
| 339 |
+
values = [10.0 ** (-exponent * index / (n - 1)) for index in range(n)]
|
| 340 |
+
if signed:
|
| 341 |
+
values = [value if index % 2 == 0 else -value for index, value in enumerate(values)]
|
| 342 |
+
return values
|
| 343 |
+
|
| 344 |
+
|
| 345 |
+
def _q_diag_qt(q: Sequence[Sequence[float]], diagonal: Sequence[float]) -> list[list[float]]:
|
| 346 |
+
n = len(diagonal)
|
| 347 |
+
return [
|
| 348 |
+
[sum(q[row][k] * diagonal[k] * q[column][k] for k in range(n)) for column in range(n)]
|
| 349 |
+
for row in range(n)
|
| 350 |
+
]
|
| 351 |
+
|
| 352 |
+
|
| 353 |
+
def _ql_diag_qr(ql: Sequence[Sequence[float]], diagonal: Sequence[float], qr: Sequence[Sequence[float]]) -> list[list[float]]:
|
| 354 |
+
n = len(diagonal)
|
| 355 |
+
return [
|
| 356 |
+
[sum(ql[row][k] * diagonal[k] * qr[column][k] for k in range(n)) for column in range(n)]
|
| 357 |
+
for row in range(n)
|
| 358 |
+
]
|
| 359 |
+
|
| 360 |
+
|
| 361 |
+
def _stable_matrix(matrix: Sequence[Sequence[float]]) -> list[list[float]]:
|
| 362 |
+
return [[float(format(value, ".17g")) for value in row] for row in matrix]
|
| 363 |
+
|
| 364 |
+
|
| 365 |
+
def _matvec(matrix: Sequence[Sequence[float]], vector: Sequence[float]) -> list[float]:
|
| 366 |
+
return [sum(value * vector[column] for column, value in enumerate(row)) for row in matrix]
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
def _known_solution(n: int) -> list[float]:
|
| 370 |
+
return [((-1.0) ** index) * (index + 1) / n for index in range(n)]
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def _slug(token: str) -> str:
|
| 374 |
+
return token.lower().replace("_", "-")
|
| 375 |
+
|
| 376 |
+
|
| 377 |
+
def _case_id(family: str, dimension: int, stratum: str, seed: int, operation: str) -> str:
|
| 378 |
+
return f"case-{_slug(family)}-n{dimension:02d}-{_slug(stratum)}-s{seed}-{_slug(operation)}"
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
def _case_descriptors() -> Iterable[dict[str, Any]]:
|
| 382 |
+
manifest = preregistration()
|
| 383 |
+
strata = manifest["condition_number_strata"]
|
| 384 |
+
for family in manifest["confirmatory_matrix_families"]:
|
| 385 |
+
for dimension in manifest["matrix_dimensions"]:
|
| 386 |
+
for stratum in strata:
|
| 387 |
+
for seed in manifest["deterministic_seeds"]:
|
| 388 |
+
for operation in family["operations"]:
|
| 389 |
+
case_id = _case_id(family["id"], dimension, stratum["id"], seed, operation)
|
| 390 |
+
yield {
|
| 391 |
+
"case_id": case_id,
|
| 392 |
+
"design": "CONFIRMATORY",
|
| 393 |
+
"matrix_family": family["id"],
|
| 394 |
+
"symmetric": family["symmetric"],
|
| 395 |
+
"dimension": dimension,
|
| 396 |
+
"condition_stratum": stratum["id"],
|
| 397 |
+
"condition_number_target": stratum["target"],
|
| 398 |
+
"seed": seed,
|
| 399 |
+
"operation": operation,
|
| 400 |
+
"execution_order_sha256": hashlib.sha256(
|
| 401 |
+
f"{manifest['execution_order_seed']}:{case_id}".encode("utf-8")
|
| 402 |
+
).hexdigest(),
|
| 403 |
+
}
|
| 404 |
+
for family in manifest["exploratory_matrix_families"]:
|
| 405 |
+
for dimension in family["dimensions"]:
|
| 406 |
+
for seed in family["seeds"]:
|
| 407 |
+
for operation in family["operations"]:
|
| 408 |
+
case_id = _case_id(family["id"], dimension, family["condition_stratum"], seed, operation)
|
| 409 |
+
yield {
|
| 410 |
+
"case_id": case_id,
|
| 411 |
+
"design": "EXPLORATORY",
|
| 412 |
+
"matrix_family": family["id"],
|
| 413 |
+
"symmetric": family["symmetric"],
|
| 414 |
+
"dimension": dimension,
|
| 415 |
+
"condition_stratum": family["condition_stratum"],
|
| 416 |
+
"condition_number_target": None,
|
| 417 |
+
"seed": seed,
|
| 418 |
+
"operation": operation,
|
| 419 |
+
"excluded_from_confirmatory_denominators": True,
|
| 420 |
+
"execution_order_sha256": hashlib.sha256(
|
| 421 |
+
f"{manifest['execution_order_seed']}:{case_id}".encode("utf-8")
|
| 422 |
+
).hexdigest(),
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
|
| 426 |
+
@lru_cache(maxsize=1)
|
| 427 |
+
def _case_index() -> dict[str, dict[str, Any]]:
|
| 428 |
+
values = {item["case_id"]: item for item in _case_descriptors()}
|
| 429 |
+
manifest = preregistration()
|
| 430 |
+
if len(values) != manifest["expected_case_counts"]["total"]:
|
| 431 |
+
raise DatasetUnavailable("GENERATED_CASE_COUNT_MISMATCH")
|
| 432 |
+
return values
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
def _matrix_for(descriptor: Mapping[str, Any]) -> list[list[float]]:
|
| 436 |
+
n = descriptor["dimension"]
|
| 437 |
+
family = descriptor["matrix_family"]
|
| 438 |
+
seed = descriptor["seed"]
|
| 439 |
+
kappa = descriptor["condition_number_target"]
|
| 440 |
+
if family == "HILBERT_SENTINEL":
|
| 441 |
+
return _stable_matrix([[1.0 / (row + column + 1) for column in range(n)] for row in range(n)])
|
| 442 |
+
diagonal = _spectrum(n, kappa, signed=family == "SYMMETRIC_INDEFINITE_GIVENS")
|
| 443 |
+
if family == "DIAGONAL_GEOMETRIC":
|
| 444 |
+
matrix = [[diagonal[row] if row == column else 0.0 for column in range(n)] for row in range(n)]
|
| 445 |
+
elif family in ("SPD_GIVENS", "SYMMETRIC_INDEFINITE_GIVENS"):
|
| 446 |
+
q = _orthogonal(n, _derived_seed(seed, family, "Q"))
|
| 447 |
+
matrix = _q_diag_qt(q, diagonal)
|
| 448 |
+
elif family == "GENERAL_SVD_GIVENS":
|
| 449 |
+
ql = _orthogonal(n, _derived_seed(seed, family, "Q_LEFT"))
|
| 450 |
+
qr = _orthogonal(n, _derived_seed(seed, family, "Q_RIGHT"))
|
| 451 |
+
matrix = _ql_diag_qr(ql, diagonal, qr)
|
| 452 |
+
else:
|
| 453 |
+
raise DatasetUnavailable("UNKNOWN_PREREGISTERED_MATRIX_FAMILY")
|
| 454 |
+
return _stable_matrix(matrix)
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def get_case(case_id: str) -> dict[str, Any]:
|
| 458 |
+
if not isinstance(case_id, str) or not _CASE_RE.fullmatch(case_id):
|
| 459 |
+
raise DatasetContractError("case_id is invalid")
|
| 460 |
+
descriptor = _case_index().get(case_id)
|
| 461 |
+
if descriptor is None:
|
| 462 |
+
raise DatasetContractError("case_id is not preregistered")
|
| 463 |
+
matrix = _matrix_for(descriptor)
|
| 464 |
+
operation = descriptor["operation"]
|
| 465 |
+
inputs: dict[str, Any] = {"matrix": matrix}
|
| 466 |
+
construction_reference: dict[str, Any] = {"state": "NOT_APPLICABLE"}
|
| 467 |
+
if operation != "SYMMETRIC_EIGENVALUES":
|
| 468 |
+
expected = _known_solution(descriptor["dimension"])
|
| 469 |
+
inputs["rhs"] = _matvec(matrix, expected)
|
| 470 |
+
construction_reference = {
|
| 471 |
+
"state": "FROZEN_CONSTRUCTION_REFERENCE",
|
| 472 |
+
"role": "fixture construction only; not the independent primary reference",
|
| 473 |
+
"values": expected,
|
| 474 |
+
}
|
| 475 |
+
if operation == "VALIDATE_REFERENCE_VECTOR":
|
| 476 |
+
inputs["expected"] = expected
|
| 477 |
+
request = {
|
| 478 |
+
"schema": _adapter.REQUEST_SCHEMA,
|
| 479 |
+
"request_id": case_id,
|
| 480 |
+
"operation": operation,
|
| 481 |
+
"inputs": inputs,
|
| 482 |
+
"tolerance": preregistration()["tolerance"],
|
| 483 |
+
}
|
| 484 |
+
request = _adapter.parse_request(request)
|
| 485 |
+
core = {
|
| 486 |
+
"schema": CASE_SCHEMA,
|
| 487 |
+
**descriptor,
|
| 488 |
+
"request": request,
|
| 489 |
+
"request_sha256": _adapter.digest_json(request),
|
| 490 |
+
"construction_reference": construction_reference,
|
| 491 |
+
"primary_reference": {"state": "SOURCE_UNAVAILABLE"},
|
| 492 |
+
"condition_number_reference": {"state": "NOT_EVALUATED"},
|
| 493 |
+
"substrate_evidence": "UNKNOWN",
|
| 494 |
+
**ZERO_UPLIFT,
|
| 495 |
+
}
|
| 496 |
+
return {**core, "fixture_sha256": _adapter.digest_json(core)}
|
| 497 |
+
|
| 498 |
+
|
| 499 |
+
def list_cases(*, offset: int = 0, limit: int = 25, family: str | None = None, operation: str | None = None) -> dict[str, Any]:
|
| 500 |
+
if offset < 0 or not 1 <= limit <= MAX_PAGE_SIZE:
|
| 501 |
+
raise DatasetContractError(f"offset must be non-negative and limit must be 1..{MAX_PAGE_SIZE}")
|
| 502 |
+
values = list(_case_index().values())
|
| 503 |
+
if family:
|
| 504 |
+
values = [item for item in values if item["matrix_family"] == family]
|
| 505 |
+
if operation:
|
| 506 |
+
values = [item for item in values if item["operation"] == operation]
|
| 507 |
+
values.sort(key=lambda item: item["execution_order_sha256"])
|
| 508 |
+
return {
|
| 509 |
+
"schema": "szl.numerics.dataset-case-list/v1",
|
| 510 |
+
"total": len(values),
|
| 511 |
+
"offset": offset,
|
| 512 |
+
"limit": limit,
|
| 513 |
+
"items": values[offset: offset + limit],
|
| 514 |
+
"items_are": "PREREGISTERED_INPUT_DESCRIPTORS_NOT_ENGINE_RESULTS",
|
| 515 |
+
**ZERO_UPLIFT,
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
def _ledger_path() -> Path:
|
| 520 |
+
configured = os.environ.get("A11OY_NUMERICS_DATASET_LEDGER", "").strip()
|
| 521 |
+
return Path(configured).expanduser() if configured else _ROOT / ".a11oy-state" / "numerics-dataset.ndjson"
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
def _read_rows() -> list[dict[str, Any]]:
|
| 525 |
+
path = _ledger_path()
|
| 526 |
+
if not path.is_file():
|
| 527 |
+
return []
|
| 528 |
+
if path.stat().st_size > MAX_LEDGER_BYTES:
|
| 529 |
+
raise DatasetUnavailable("LEDGER_SIZE_LIMIT_EXCEEDED")
|
| 530 |
+
rows: list[dict[str, Any]] = []
|
| 531 |
+
for line_number, raw in enumerate(path.read_bytes().splitlines(), start=1):
|
| 532 |
+
if not raw:
|
| 533 |
+
continue
|
| 534 |
+
if len(raw) > MAX_ROW_BYTES:
|
| 535 |
+
raise DatasetUnavailable(f"LEDGER_ROW_SIZE_LIMIT_EXCEEDED:{line_number}")
|
| 536 |
+
try:
|
| 537 |
+
value = json.loads(raw.decode("utf-8"))
|
| 538 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 539 |
+
raise DatasetUnavailable(f"LEDGER_ROW_INVALID:{line_number}") from exc
|
| 540 |
+
if not isinstance(value, dict) or value.get("schema") != ROW_SCHEMA:
|
| 541 |
+
raise DatasetUnavailable(f"LEDGER_ROW_SCHEMA_INVALID:{line_number}")
|
| 542 |
+
rows.append(value)
|
| 543 |
+
if len(rows) > MAX_LEDGER_ROWS:
|
| 544 |
+
raise DatasetUnavailable("LEDGER_ROW_LIMIT_EXCEEDED")
|
| 545 |
+
return rows
|
| 546 |
+
|
| 547 |
+
|
| 548 |
+
def list_results(*, offset: int = 0, limit: int = 25, case_id: str | None = None) -> dict[str, Any]:
|
| 549 |
+
if offset < 0 or not 1 <= limit <= MAX_PAGE_SIZE:
|
| 550 |
+
raise DatasetContractError(f"offset must be non-negative and limit must be 1..{MAX_PAGE_SIZE}")
|
| 551 |
+
rows = _read_rows()
|
| 552 |
+
if case_id:
|
| 553 |
+
rows = [row for row in rows if row.get("case_id") == case_id]
|
| 554 |
+
rows.reverse()
|
| 555 |
+
return {
|
| 556 |
+
"schema": "szl.numerics.dataset-result-list/v1",
|
| 557 |
+
"total": len(rows),
|
| 558 |
+
"offset": offset,
|
| 559 |
+
"limit": limit,
|
| 560 |
+
"items": rows[offset: offset + limit],
|
| 561 |
+
"ledger_semantics": "APPEND_ONLY_NEWEST_FIRST",
|
| 562 |
+
**ZERO_UPLIFT,
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
|
| 566 |
+
def _vector_norm(vector: Sequence[float]) -> float:
|
| 567 |
+
return math.sqrt(sum(value * value for value in vector))
|
| 568 |
+
|
| 569 |
+
|
| 570 |
+
def _matrix_norm2_diagnostic(matrix: Sequence[Sequence[float]]) -> float:
|
| 571 |
+
"""Deterministic binary64 power iteration; explicitly not a high-precision reference."""
|
| 572 |
+
|
| 573 |
+
n = len(matrix)
|
| 574 |
+
vector = [1.0 / math.sqrt(n)] * n
|
| 575 |
+
for _ in range(96):
|
| 576 |
+
av = _matvec(matrix, vector)
|
| 577 |
+
ata_v = [sum(matrix[row][column] * av[row] for row in range(n)) for column in range(n)]
|
| 578 |
+
size = _vector_norm(ata_v)
|
| 579 |
+
if size == 0.0:
|
| 580 |
+
return 0.0
|
| 581 |
+
next_vector = [value / size for value in ata_v]
|
| 582 |
+
delta = _vector_norm([left - right for left, right in zip(next_vector, vector)])
|
| 583 |
+
vector = next_vector
|
| 584 |
+
if delta <= 1.0e-15:
|
| 585 |
+
break
|
| 586 |
+
return _vector_norm(_matvec(matrix, vector))
|
| 587 |
+
|
| 588 |
+
|
| 589 |
+
def _relative_error(actual: Sequence[float], expected: Sequence[float]) -> float:
|
| 590 |
+
numerator = _vector_norm([left - right for left, right in zip(actual, expected)])
|
| 591 |
+
denominator = _vector_norm(expected)
|
| 592 |
+
if denominator == 0.0:
|
| 593 |
+
return 0.0 if numerator == 0.0 else math.inf
|
| 594 |
+
return numerator / denominator
|
| 595 |
+
|
| 596 |
+
|
| 597 |
+
def _within(left: float, right: float, tolerance: Mapping[str, float]) -> bool:
|
| 598 |
+
return abs(left - right) <= tolerance["absolute"] + tolerance["relative"] * max(abs(left), abs(right))
|
| 599 |
+
|
| 600 |
+
|
| 601 |
+
def _diagnostics(case: Mapping[str, Any], values: Sequence[float], reference: Mapping[str, Any]) -> dict[str, Any]:
|
| 602 |
+
request = case["request"]
|
| 603 |
+
matrix = request["inputs"]["matrix"]
|
| 604 |
+
operation = request["operation"]
|
| 605 |
+
n = len(matrix)
|
| 606 |
+
threshold = 100.0 * n * preregistration()["machine_epsilon_binary64"]
|
| 607 |
+
base: dict[str, Any] = {
|
| 608 |
+
"diagnostic_precision": "PYTHON_BINARY64",
|
| 609 |
+
"matrix_norm2_method": "DETERMINISTIC_POWER_ITERATION_NOT_PRIMARY_REFERENCE",
|
| 610 |
+
"absolute_residual_norm2": None,
|
| 611 |
+
"relative_residual": None,
|
| 612 |
+
"normwise_backward_error": None,
|
| 613 |
+
"forward_error": None,
|
| 614 |
+
"maximum_elementwise_reference_error": None,
|
| 615 |
+
"reference_state": "NOT_EVALUATED",
|
| 616 |
+
"trace_invariant": None,
|
| 617 |
+
"frobenius_invariant": None,
|
| 618 |
+
"quality_gate_threshold": threshold,
|
| 619 |
+
"quality_gate": "NOT_EVALUATED",
|
| 620 |
+
}
|
| 621 |
+
if operation in ("MATRIX_SOLVE", "VALIDATE_REFERENCE_VECTOR"):
|
| 622 |
+
rhs = request["inputs"]["rhs"]
|
| 623 |
+
residual_vector = [right - left for right, left in zip(rhs, _matvec(matrix, values))]
|
| 624 |
+
residual = _vector_norm(residual_vector)
|
| 625 |
+
denominator = _matrix_norm2_diagnostic(matrix) * _vector_norm(values) + _vector_norm(rhs)
|
| 626 |
+
backward = 0.0 if residual == 0.0 and denominator == 0.0 else (math.inf if denominator == 0.0 else residual / denominator)
|
| 627 |
+
base.update({
|
| 628 |
+
"absolute_residual_norm2": residual,
|
| 629 |
+
"relative_residual": backward,
|
| 630 |
+
"normwise_backward_error": backward,
|
| 631 |
+
"quality_gate": "PASS" if math.isfinite(backward) and backward <= threshold else "FAIL",
|
| 632 |
+
})
|
| 633 |
+
else:
|
| 634 |
+
trace_matrix = sum(matrix[index][index] for index in range(n))
|
| 635 |
+
trace_values = sum(values)
|
| 636 |
+
norm_f_squared = sum(value * value for row in matrix for value in row)
|
| 637 |
+
value_sq_sum = sum(value * value for value in values)
|
| 638 |
+
trace_invariant = abs(trace_values - trace_matrix) / max(1.0, abs(trace_matrix))
|
| 639 |
+
frobenius_invariant = abs(value_sq_sum - norm_f_squared) / max(1.0, norm_f_squared)
|
| 640 |
+
base.update({
|
| 641 |
+
"trace_invariant": trace_invariant,
|
| 642 |
+
"frobenius_invariant": frobenius_invariant,
|
| 643 |
+
"quality_gate": "PASS" if trace_invariant <= threshold and frobenius_invariant <= threshold else "FAIL",
|
| 644 |
+
})
|
| 645 |
+
if reference["state"] == "MEASURED":
|
| 646 |
+
expected = reference["values"]
|
| 647 |
+
base.update({
|
| 648 |
+
"forward_error": _relative_error(values, expected),
|
| 649 |
+
"maximum_elementwise_reference_error": max(abs(left - right) for left, right in zip(values, expected)),
|
| 650 |
+
"reference_state": "REFERENCE_MATCH" if all(
|
| 651 |
+
_within(left, right, request["tolerance"]) for left, right in zip(values, expected)
|
| 652 |
+
) else "REFERENCE_CONFLICT",
|
| 653 |
+
"reference_implementation": reference["implementation"],
|
| 654 |
+
"reference_evidence_sha256": reference["evidence_sha256"],
|
| 655 |
+
})
|
| 656 |
+
return base
|
| 657 |
+
|
| 658 |
+
|
| 659 |
+
def _parse_ingest(payload: Mapping[str, Any]) -> dict[str, Any]:
|
| 660 |
+
required = {"schema", "run_id", "case_id", "engine", "outcome", "engine_evidence", "containment", "resources", "reference", "observed_at_utc"}
|
| 661 |
+
obj = _strict(payload, required, "ingest")
|
| 662 |
+
if obj["schema"] != INGEST_SCHEMA:
|
| 663 |
+
raise DatasetContractError(f"schema must be {INGEST_SCHEMA}")
|
| 664 |
+
if not isinstance(obj["run_id"], str) or not _ID_RE.fullmatch(obj["run_id"]):
|
| 665 |
+
raise DatasetContractError("run_id is invalid")
|
| 666 |
+
case = get_case(obj["case_id"])
|
| 667 |
+
if obj["engine"] not in _adapter.ENGINES:
|
| 668 |
+
raise DatasetContractError("engine must be octave or matlab")
|
| 669 |
+
outcome = obj["outcome"]
|
| 670 |
+
if not isinstance(outcome, Mapping) or outcome.get("state") not in ("RESULT", "UNAVAILABLE"):
|
| 671 |
+
raise DatasetContractError("outcome.state must be RESULT or UNAVAILABLE")
|
| 672 |
+
if outcome["state"] == "RESULT":
|
| 673 |
+
outcome = _strict(outcome, {"state", "values"}, "outcome")
|
| 674 |
+
raw_values = outcome["values"]
|
| 675 |
+
if not isinstance(raw_values, Sequence) or isinstance(raw_values, (str, bytes, bytearray)):
|
| 676 |
+
raise DatasetContractError("outcome.values must be an array")
|
| 677 |
+
if len(raw_values) != case["dimension"]:
|
| 678 |
+
raise DatasetContractError(f"outcome.values must contain exactly {case['dimension']} numbers")
|
| 679 |
+
outcome = {"state": "RESULT", "values": [_finite(value, f"outcome.values[{index}]") for index, value in enumerate(raw_values)]}
|
| 680 |
+
else:
|
| 681 |
+
outcome = _strict(outcome, {"state", "reason"}, "outcome")
|
| 682 |
+
if not isinstance(outcome["reason"], str) or not 1 <= len(outcome["reason"]) <= 160:
|
| 683 |
+
raise DatasetContractError("outcome.reason must contain 1..160 characters")
|
| 684 |
+
outcome = dict(outcome)
|
| 685 |
+
engine_evidence = _strict(
|
| 686 |
+
obj["engine_evidence"],
|
| 687 |
+
{"version", "version_evidence_sha256", "executable_sha256", "license_state", "offline_license_state"},
|
| 688 |
+
"engine_evidence",
|
| 689 |
+
)
|
| 690 |
+
version = engine_evidence["version"]
|
| 691 |
+
if version is not None and (not isinstance(version, str) or not 1 <= len(version) <= 120):
|
| 692 |
+
raise DatasetContractError("engine_evidence.version must be null or 1..120 characters")
|
| 693 |
+
engine_evidence = {
|
| 694 |
+
"version": version,
|
| 695 |
+
"version_evidence_sha256": _sha_or_none(engine_evidence["version_evidence_sha256"], "engine_evidence.version_evidence_sha256"),
|
| 696 |
+
"executable_sha256": _sha_or_none(engine_evidence["executable_sha256"], "engine_evidence.executable_sha256"),
|
| 697 |
+
"license_state": engine_evidence["license_state"],
|
| 698 |
+
"offline_license_state": engine_evidence["offline_license_state"],
|
| 699 |
+
}
|
| 700 |
+
if engine_evidence["license_state"] not in ("OPERATOR_REVIEWED", "REVIEW_REQUIRED", "UNKNOWN"):
|
| 701 |
+
raise DatasetContractError("engine_evidence.license_state is invalid")
|
| 702 |
+
if engine_evidence["offline_license_state"] not in ("CONFIGURED", "UNAVAILABLE", "NOT_APPLICABLE", "UNKNOWN"):
|
| 703 |
+
raise DatasetContractError("engine_evidence.offline_license_state is invalid")
|
| 704 |
+
containment = _strict(obj["containment"], {"network_state", "evidence_sha256"}, "containment")
|
| 705 |
+
if containment["network_state"] not in ("DENIED", "UNAVAILABLE", "UNKNOWN"):
|
| 706 |
+
raise DatasetContractError("containment.network_state is invalid")
|
| 707 |
+
containment = {"network_state": containment["network_state"], "evidence_sha256": _sha_or_none(containment["evidence_sha256"], "containment.evidence_sha256")}
|
| 708 |
+
resources = _strict(
|
| 709 |
+
obj["resources"],
|
| 710 |
+
{"wall_time_ns", "child_user_cpu_ns", "child_system_cpu_ns", "peak_resident_bytes", "request_bytes", "response_bytes", "log_bytes"},
|
| 711 |
+
"resources",
|
| 712 |
+
)
|
| 713 |
+
resources = {name: _nullable_uint(value, f"resources.{name}") for name, value in resources.items()}
|
| 714 |
+
reference = obj["reference"]
|
| 715 |
+
if not isinstance(reference, Mapping) or reference.get("state") not in ("SOURCE_UNAVAILABLE", "MEASURED"):
|
| 716 |
+
raise DatasetContractError("reference.state must be SOURCE_UNAVAILABLE or MEASURED")
|
| 717 |
+
if reference["state"] == "SOURCE_UNAVAILABLE":
|
| 718 |
+
reference = dict(_strict(reference, {"state"}, "reference"))
|
| 719 |
+
else:
|
| 720 |
+
reference = _strict(reference, {"state", "implementation", "values", "evidence_sha256"}, "reference")
|
| 721 |
+
if reference["implementation"] != "PYTHON_MPMATH_100DP":
|
| 722 |
+
raise DatasetContractError("only the preregistered PYTHON_MPMATH_100DP primary reference is accepted")
|
| 723 |
+
values = reference["values"]
|
| 724 |
+
if not isinstance(values, Sequence) or isinstance(values, (str, bytes, bytearray)) or len(values) != case["dimension"]:
|
| 725 |
+
raise DatasetContractError(f"reference.values must contain exactly {case['dimension']} numbers")
|
| 726 |
+
reference = {
|
| 727 |
+
"state": "MEASURED",
|
| 728 |
+
"implementation": "PYTHON_MPMATH_100DP",
|
| 729 |
+
"values": [_finite(value, f"reference.values[{index}]") for index, value in enumerate(values)],
|
| 730 |
+
"evidence_sha256": _sha_or_none(reference["evidence_sha256"], "reference.evidence_sha256"),
|
| 731 |
+
}
|
| 732 |
+
if reference["evidence_sha256"] is None:
|
| 733 |
+
raise DatasetContractError("measured primary reference requires evidence_sha256")
|
| 734 |
+
return {
|
| 735 |
+
"run_id": obj["run_id"],
|
| 736 |
+
"case": case,
|
| 737 |
+
"engine": obj["engine"],
|
| 738 |
+
"outcome": outcome,
|
| 739 |
+
"engine_evidence": engine_evidence,
|
| 740 |
+
"containment": containment,
|
| 741 |
+
"resources": resources,
|
| 742 |
+
"reference": reference,
|
| 743 |
+
"observed_at_utc": _utc_timestamp(obj["observed_at_utc"]),
|
| 744 |
+
}
|
| 745 |
+
|
| 746 |
+
|
| 747 |
+
def _evidence_gate(parsed: Mapping[str, Any]) -> tuple[str, str | None]:
|
| 748 |
+
if parsed["outcome"]["state"] == "UNAVAILABLE":
|
| 749 |
+
return "UNAVAILABLE", parsed["outcome"]["reason"]
|
| 750 |
+
evidence = parsed["engine_evidence"]
|
| 751 |
+
containment = parsed["containment"]
|
| 752 |
+
resources = parsed["resources"]
|
| 753 |
+
if containment["network_state"] != "DENIED" or containment["evidence_sha256"] is None:
|
| 754 |
+
return "REFUSED", "NETWORK_DENIAL_EVIDENCE_UNAVAILABLE"
|
| 755 |
+
if evidence["version"] is None or evidence["version_evidence_sha256"] is None or evidence["executable_sha256"] is None:
|
| 756 |
+
return "REFUSED", "ENGINE_VERSION_EVIDENCE_UNAVAILABLE"
|
| 757 |
+
if evidence["license_state"] != "OPERATOR_REVIEWED":
|
| 758 |
+
return "REFUSED", "ENGINE_LICENSE_REVIEW_UNAVAILABLE"
|
| 759 |
+
if parsed["engine"] == "matlab" and evidence["offline_license_state"] != "CONFIGURED":
|
| 760 |
+
return "REFUSED", "MATLAB_OFFLINE_LICENSE_STATE_UNAVAILABLE"
|
| 761 |
+
if parsed["engine"] == "octave" and evidence["offline_license_state"] != "NOT_APPLICABLE":
|
| 762 |
+
return "REFUSED", "OCTAVE_OFFLINE_LICENSE_STATE_MUST_BE_NOT_APPLICABLE"
|
| 763 |
+
if resources["wall_time_ns"] is None:
|
| 764 |
+
return "REFUSED", "WALL_TIME_MEASUREMENT_UNAVAILABLE"
|
| 765 |
+
return "RESULT", None
|
| 766 |
+
|
| 767 |
+
|
| 768 |
+
def _latest_other(rows: Sequence[Mapping[str, Any]], case_id: str, engine: str) -> Mapping[str, Any] | None:
|
| 769 |
+
for row in reversed(rows):
|
| 770 |
+
if row.get("case_id") == case_id and row.get("engine") != engine and row.get("row_state") == "RESULT":
|
| 771 |
+
return row
|
| 772 |
+
return None
|
| 773 |
+
|
| 774 |
+
|
| 775 |
+
def ingest_result(payload: Mapping[str, Any]) -> dict[str, Any]:
|
| 776 |
+
parsed = _parse_ingest(payload)
|
| 777 |
+
with _LEDGER_LOCK:
|
| 778 |
+
rows = _read_rows()
|
| 779 |
+
if len(rows) >= MAX_LEDGER_ROWS:
|
| 780 |
+
raise DatasetUnavailable("LEDGER_ROW_LIMIT_EXCEEDED")
|
| 781 |
+
if any(row.get("run_id") == parsed["run_id"] for row in rows):
|
| 782 |
+
raise DatasetContractError("run_id already exists in the append-only ledger")
|
| 783 |
+
row_state, reason = _evidence_gate(parsed)
|
| 784 |
+
values = parsed["outcome"].get("values") if row_state == "RESULT" else None
|
| 785 |
+
diagnostics = _diagnostics(parsed["case"], values, parsed["reference"]) if values is not None else None
|
| 786 |
+
comparison_state = "UNAVAILABLE" if row_state == "UNAVAILABLE" else ("REFUSED" if row_state == "REFUSED" else "NOT_EVALUATED")
|
| 787 |
+
compared_to = None
|
| 788 |
+
if row_state == "RESULT":
|
| 789 |
+
other = _latest_other(rows, parsed["case"]["case_id"], parsed["engine"])
|
| 790 |
+
if other is not None:
|
| 791 |
+
compared_to = other["run_id"]
|
| 792 |
+
tolerance = parsed["case"]["request"]["tolerance"]
|
| 793 |
+
pair_matches = all(_within(left, right, tolerance) for left, right in zip(values, other["values"]))
|
| 794 |
+
own_gate = diagnostics["quality_gate"] == "PASS"
|
| 795 |
+
other_gate = (other.get("diagnostics") or {}).get("quality_gate") == "PASS"
|
| 796 |
+
comparison_state = "MATCH" if pair_matches and own_gate and other_gate else "CONFLICT"
|
| 797 |
+
core = {
|
| 798 |
+
"schema": ROW_SCHEMA,
|
| 799 |
+
"sequence": len(rows) + 1,
|
| 800 |
+
"run_id": parsed["run_id"],
|
| 801 |
+
"case_id": parsed["case"]["case_id"],
|
| 802 |
+
"fixture_sha256": parsed["case"]["fixture_sha256"],
|
| 803 |
+
"request_sha256": parsed["case"]["request_sha256"],
|
| 804 |
+
"engine": parsed["engine"],
|
| 805 |
+
"row_state": row_state,
|
| 806 |
+
"comparison_state": comparison_state,
|
| 807 |
+
"compared_to_run_id": compared_to,
|
| 808 |
+
"reason": reason,
|
| 809 |
+
"values": values,
|
| 810 |
+
"values_sha256": _adapter.digest_json(values) if values is not None else None,
|
| 811 |
+
"diagnostics": diagnostics,
|
| 812 |
+
"engine_evidence": parsed["engine_evidence"],
|
| 813 |
+
"containment": parsed["containment"],
|
| 814 |
+
"resources": parsed["resources"],
|
| 815 |
+
"reference": {key: value for key, value in parsed["reference"].items() if key != "values"},
|
| 816 |
+
"observed_at_utc": parsed["observed_at_utc"],
|
| 817 |
+
"evidence_label": "MEASURED" if row_state == "RESULT" else "UNKNOWN",
|
| 818 |
+
"evidence_origin": "AUTHENTICATED_APPEND_ONLY_INGESTION_NOT_LOCAL_ENGINE_EXECUTION",
|
| 819 |
+
"substrate_evidence": "UNKNOWN",
|
| 820 |
+
"signature_state": "UNSIGNED_INTEGRITY_CHAIN",
|
| 821 |
+
"previous_row_sha256": rows[-1]["row_sha256"] if rows else None,
|
| 822 |
+
**ZERO_UPLIFT,
|
| 823 |
+
}
|
| 824 |
+
row = {**core, "row_sha256": _adapter.digest_json(core)}
|
| 825 |
+
encoded = _adapter.canonical_json(row) + b"\n"
|
| 826 |
+
if len(encoded) > MAX_ROW_BYTES:
|
| 827 |
+
raise DatasetContractError("result row exceeds the 64 KiB append ceiling")
|
| 828 |
+
path = _ledger_path()
|
| 829 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 830 |
+
with path.open("ab") as handle:
|
| 831 |
+
handle.write(encoded)
|
| 832 |
+
handle.flush()
|
| 833 |
+
os.fsync(handle.fileno())
|
| 834 |
+
return row
|
| 835 |
+
|
| 836 |
+
|
| 837 |
+
def _ingest_configured() -> bool:
|
| 838 |
+
digest = os.environ.get("A11OY_NUMERICS_DATASET_INGEST_TOKEN_SHA256", "").strip().lower()
|
| 839 |
+
return bool(_SHA256_RE.fullmatch(digest))
|
| 840 |
+
|
| 841 |
+
|
| 842 |
+
def _authorized(token: str | None) -> bool:
|
| 843 |
+
expected = os.environ.get("A11OY_NUMERICS_DATASET_INGEST_TOKEN_SHA256", "").strip().lower()
|
| 844 |
+
if not _SHA256_RE.fullmatch(expected) or not token:
|
| 845 |
+
return False
|
| 846 |
+
return hmac.compare_digest(hashlib.sha256(token.encode("utf-8")).hexdigest(), expected)
|
| 847 |
+
|
| 848 |
+
|
| 849 |
+
def dataset_status() -> dict[str, Any]:
|
| 850 |
+
manifest = preregistration()
|
| 851 |
+
curriculum = formula_curriculum()
|
| 852 |
+
rows = _read_rows()
|
| 853 |
+
classifications: dict[str, int] = {}
|
| 854 |
+
for row in rows:
|
| 855 |
+
token = row.get("comparison_state", "UNKNOWN")
|
| 856 |
+
classifications[token] = classifications.get(token, 0) + 1
|
| 857 |
+
runtime = _adapter.engine_status()
|
| 858 |
+
return {
|
| 859 |
+
"schema": STATUS_SCHEMA,
|
| 860 |
+
"service_state": "READY" if manifest["frozen_before_execution"] else "UNAVAILABLE",
|
| 861 |
+
"preregistration": {
|
| 862 |
+
"protocol_id": manifest["protocol_id"],
|
| 863 |
+
"state": manifest["state"],
|
| 864 |
+
"manifest_sha256": _adapter.digest_json(manifest),
|
| 865 |
+
"inputs_frozen": manifest["frozen_before_execution"],
|
| 866 |
+
"case_count": len(_case_index()),
|
| 867 |
+
"confirmatory_case_count": manifest["expected_case_counts"]["confirmatory"],
|
| 868 |
+
"exploratory_case_count": manifest["expected_case_counts"]["exploratory"],
|
| 869 |
+
},
|
| 870 |
+
"result_ledger": {
|
| 871 |
+
"row_count": len(rows),
|
| 872 |
+
"classification_counts": classifications,
|
| 873 |
+
"append_only": True,
|
| 874 |
+
"ingest_gate": "CONFIGURED" if _ingest_configured() else "UNAVAILABLE",
|
| 875 |
+
"path_disclosed": False,
|
| 876 |
+
},
|
| 877 |
+
"local_runtime": {
|
| 878 |
+
"octave": runtime["engines"]["octave"]["execution_state"],
|
| 879 |
+
"matlab": runtime["engines"]["matlab"]["execution_state"],
|
| 880 |
+
"network_isolation": runtime["controls"]["network_isolation"],
|
| 881 |
+
"network_denial_evidence": "NOT_EVALUATED",
|
| 882 |
+
"substrate_evidence": "UNKNOWN",
|
| 883 |
+
},
|
| 884 |
+
"reference_state": "MEASURED_PER_ROW_ONLY_WHEN_PINNED_EVIDENCE_IS_INGESTED",
|
| 885 |
+
"formula_curriculum": {
|
| 886 |
+
"state": curriculum["state"],
|
| 887 |
+
**curriculum["counts"],
|
| 888 |
+
"proof_uplift": 0,
|
| 889 |
+
"trust_uplift": 0,
|
| 890 |
+
},
|
| 891 |
+
"interpretation_guard": "MATCH is bounded cross-engine agreement for one frozen case; it is not proof or general correctness.",
|
| 892 |
+
**ZERO_UPLIFT,
|
| 893 |
+
}
|
| 894 |
+
|
| 895 |
+
|
| 896 |
+
def _page_int(raw: str | None, default: int, name: str) -> int:
|
| 897 |
+
if raw is None:
|
| 898 |
+
return default
|
| 899 |
+
try:
|
| 900 |
+
value = int(raw)
|
| 901 |
+
except ValueError as exc:
|
| 902 |
+
raise DatasetContractError(f"{name} must be an integer") from exc
|
| 903 |
+
return value
|
| 904 |
+
|
| 905 |
+
|
| 906 |
+
def register(app: Any, ns: str = "a11oy") -> str:
|
| 907 |
+
"""Register read APIs and the authenticated append-only result endpoint."""
|
| 908 |
+
|
| 909 |
+
from fastapi.responses import JSONResponse
|
| 910 |
+
|
| 911 |
+
prefix = f"/api/{ns}/v1/numerics/dataset"
|
| 912 |
+
|
| 913 |
+
@app.get(f"{prefix}/status")
|
| 914 |
+
async def numerics_dataset_status() -> JSONResponse:
|
| 915 |
+
try:
|
| 916 |
+
return JSONResponse(dataset_status())
|
| 917 |
+
except DatasetUnavailable as exc:
|
| 918 |
+
return JSONResponse({"schema": STATUS_SCHEMA, "service_state": "UNAVAILABLE", "reason": str(exc), **ZERO_UPLIFT}, status_code=503)
|
| 919 |
+
|
| 920 |
+
@app.get(f"{prefix}/cases")
|
| 921 |
+
async def numerics_dataset_cases(request: Request) -> JSONResponse:
|
| 922 |
+
try:
|
| 923 |
+
result = list_cases(
|
| 924 |
+
offset=_page_int(request.query_params.get("offset"), 0, "offset"),
|
| 925 |
+
limit=_page_int(request.query_params.get("limit"), 25, "limit"),
|
| 926 |
+
family=request.query_params.get("family"),
|
| 927 |
+
operation=request.query_params.get("operation"),
|
| 928 |
+
)
|
| 929 |
+
except (DatasetContractError, DatasetUnavailable) as exc:
|
| 930 |
+
return JSONResponse({"state": "REJECTED", "error": str(exc), **ZERO_UPLIFT}, status_code=422)
|
| 931 |
+
return JSONResponse(result)
|
| 932 |
+
|
| 933 |
+
@app.get(f"{prefix}/cases/{{case_id}}")
|
| 934 |
+
async def numerics_dataset_case(case_id: str) -> JSONResponse:
|
| 935 |
+
try:
|
| 936 |
+
return JSONResponse(get_case(case_id))
|
| 937 |
+
except DatasetContractError as exc:
|
| 938 |
+
return JSONResponse({"state": "REJECTED", "error": str(exc), **ZERO_UPLIFT}, status_code=404)
|
| 939 |
+
|
| 940 |
+
@app.get(f"{prefix}/results")
|
| 941 |
+
async def numerics_dataset_results(request: Request) -> JSONResponse:
|
| 942 |
+
try:
|
| 943 |
+
result = list_results(
|
| 944 |
+
offset=_page_int(request.query_params.get("offset"), 0, "offset"),
|
| 945 |
+
limit=_page_int(request.query_params.get("limit"), 25, "limit"),
|
| 946 |
+
case_id=request.query_params.get("case_id"),
|
| 947 |
+
)
|
| 948 |
+
except (DatasetContractError, DatasetUnavailable) as exc:
|
| 949 |
+
return JSONResponse({"state": "UNAVAILABLE", "error": str(exc), **ZERO_UPLIFT}, status_code=503)
|
| 950 |
+
return JSONResponse(result)
|
| 951 |
+
|
| 952 |
+
@app.get(f"{prefix}/curriculum/formulas")
|
| 953 |
+
async def numerics_formula_curriculum() -> JSONResponse:
|
| 954 |
+
try:
|
| 955 |
+
return JSONResponse(formula_curriculum())
|
| 956 |
+
except DatasetUnavailable as exc:
|
| 957 |
+
return JSONResponse({
|
| 958 |
+
"schema": CURRICULUM_SCHEMA,
|
| 959 |
+
"state": "UNAVAILABLE",
|
| 960 |
+
"reason": str(exc),
|
| 961 |
+
**ZERO_UPLIFT,
|
| 962 |
+
}, status_code=503)
|
| 963 |
+
|
| 964 |
+
@app.post(f"{prefix}/results")
|
| 965 |
+
async def numerics_dataset_ingest(request: Request) -> JSONResponse:
|
| 966 |
+
if not _ingest_configured():
|
| 967 |
+
return JSONResponse({"state": "UNAVAILABLE", "reason": "INGEST_TOKEN_NOT_CONFIGURED", **ZERO_UPLIFT}, status_code=503)
|
| 968 |
+
if not _authorized(request.headers.get("x-a11oy-numerics-ingest-key")):
|
| 969 |
+
return JSONResponse({"state": "REFUSED", "reason": "INGEST_AUTHENTICATION_FAILED", **ZERO_UPLIFT}, status_code=401)
|
| 970 |
+
try:
|
| 971 |
+
payload = await _adapter._bounded_json_body(request)
|
| 972 |
+
row = ingest_result(payload)
|
| 973 |
+
except DatasetContractError as exc:
|
| 974 |
+
return JSONResponse({"state": "REJECTED", "error": str(exc), **ZERO_UPLIFT}, status_code=422)
|
| 975 |
+
except DatasetUnavailable as exc:
|
| 976 |
+
return JSONResponse({"state": "UNAVAILABLE", "error": str(exc), **ZERO_UPLIFT}, status_code=503)
|
| 977 |
+
return JSONResponse(row, status_code=201)
|
| 978 |
+
|
| 979 |
+
return (
|
| 980 |
+
"Numerics dataset registered: "
|
| 981 |
+
f"{prefix}/status · cases · case detail · append-only results; proof uplift=0"
|
| 982 |
+
)
|
| 983 |
+
|
| 984 |
+
|
| 985 |
+
__all__ = [
|
| 986 |
+
"CASE_SCHEMA",
|
| 987 |
+
"CURRICULUM_SCHEMA",
|
| 988 |
+
"DatasetContractError",
|
| 989 |
+
"DatasetUnavailable",
|
| 990 |
+
"INGEST_SCHEMA",
|
| 991 |
+
"ROW_SCHEMA",
|
| 992 |
+
"dataset_status",
|
| 993 |
+
"formula_curriculum",
|
| 994 |
+
"get_case",
|
| 995 |
+
"ingest_result",
|
| 996 |
+
"list_cases",
|
| 997 |
+
"list_results",
|
| 998 |
+
"preregistration",
|
| 999 |
+
"register",
|
| 1000 |
+
]
|
|
@@ -0,0 +1,482 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Fail-closed executor for the preregistered MATLAB/Octave comparison.
|
| 3 |
+
|
| 4 |
+
Taxonomy home: services/numerics. The frozen 1,328-case design is read from
|
| 5 |
+
``szl_numerics_dataset``. A run starts only when both external engines, POSIX
|
| 6 |
+
resource limits, a fresh ``unshare --net`` namespace, explicit operator
|
| 7 |
+
license review, and a 100-decimal-place mpmath reference are available.
|
| 8 |
+
Missing evidence produces a blocker receipt and zero engine invocations.
|
| 9 |
+
|
| 10 |
+
This module never installs or bundles MATLAB, Octave, mpmath, licenses, model
|
| 11 |
+
weights, or datasets. ``MATCH`` means bounded agreement for one frozen case;
|
| 12 |
+
it is not mathematical proof or general correctness.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
import argparse
|
| 16 |
+
import datetime as _datetime
|
| 17 |
+
import hashlib
|
| 18 |
+
import importlib
|
| 19 |
+
import json
|
| 20 |
+
import os
|
| 21 |
+
import platform
|
| 22 |
+
import subprocess
|
| 23 |
+
import sys
|
| 24 |
+
import tempfile
|
| 25 |
+
import time
|
| 26 |
+
from pathlib import Path
|
| 27 |
+
from typing import Any, Iterable, Mapping
|
| 28 |
+
|
| 29 |
+
import szl_numerics_adapter as _adapter
|
| 30 |
+
import szl_numerics_dataset as _dataset
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
PREFLIGHT_SCHEMA = "szl.numerics.experiment-preflight/v1"
|
| 34 |
+
EXPERIMENT_SCHEMA = "szl.numerics.preregistered-experiment/v1"
|
| 35 |
+
REFERENCE_SCHEMA = "szl.numerics.mpmath-reference/v1"
|
| 36 |
+
ZERO_UPLIFT = {"proof_uplift": 0, "trust_uplift": 0}
|
| 37 |
+
_ROOT = Path(__file__).resolve().parent
|
| 38 |
+
_ISOLATION_HELPER = _ROOT / "numerics" / "isolation_probe.py"
|
| 39 |
+
_MAX_VERSION_OUTPUT_BYTES = 64 * 1024
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class ExperimentUnavailable(RuntimeError):
|
| 43 |
+
"""A mandatory execution or evidence boundary is unavailable."""
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def _sha256_bytes(value: bytes) -> str:
|
| 47 |
+
return hashlib.sha256(value).hexdigest()
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def _sha256_file(path: Path) -> str:
|
| 51 |
+
digest = hashlib.sha256()
|
| 52 |
+
with path.open("rb") as handle:
|
| 53 |
+
for block in iter(lambda: handle.read(1024 * 1024), b""):
|
| 54 |
+
digest.update(block)
|
| 55 |
+
return digest.hexdigest()
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def _utc_now() -> str:
|
| 59 |
+
return _datetime.datetime.now(_datetime.timezone.utc).isoformat().replace("+00:00", "Z")
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def _child_env(work: Path) -> dict[str, str]:
|
| 63 |
+
"""Return the fixed, secret-free environment for evidence-only children."""
|
| 64 |
+
|
| 65 |
+
return {
|
| 66 |
+
"HOME": str(work),
|
| 67 |
+
"TMPDIR": str(work),
|
| 68 |
+
"LANG": "C.UTF-8",
|
| 69 |
+
"LC_ALL": "C.UTF-8",
|
| 70 |
+
"PATH": "/usr/bin:/bin",
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def experiment_plan() -> dict[str, Any]:
|
| 75 |
+
manifest = _dataset.preregistration()
|
| 76 |
+
return {
|
| 77 |
+
"protocol_id": manifest["protocol_id"],
|
| 78 |
+
"protocol_version": manifest["protocol_version"],
|
| 79 |
+
"preregistration_sha256": _adapter.digest_json(manifest),
|
| 80 |
+
"frozen_before_execution": manifest["frozen_before_execution"],
|
| 81 |
+
"matrix_families": [item["id"] for item in manifest["confirmatory_matrix_families"]],
|
| 82 |
+
"exploratory_families": [item["id"] for item in manifest["exploratory_matrix_families"]],
|
| 83 |
+
"dimensions": manifest["matrix_dimensions"],
|
| 84 |
+
"condition_number_strata": manifest["condition_number_strata"],
|
| 85 |
+
"seeds": manifest["deterministic_seeds"],
|
| 86 |
+
"tolerance": manifest["tolerance"],
|
| 87 |
+
"engines": manifest["engines"],
|
| 88 |
+
"case_counts": manifest["expected_case_counts"],
|
| 89 |
+
"planned_engine_runs": manifest["expected_case_counts"]["total"] * len(manifest["engines"]),
|
| 90 |
+
"result_claim": "NO_ENGINE_RESULT_IN_PLAN",
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def _mpmath_status() -> dict[str, Any]:
|
| 95 |
+
try:
|
| 96 |
+
module = importlib.import_module("mpmath")
|
| 97 |
+
except (ImportError, OSError):
|
| 98 |
+
return {"state": "UNAVAILABLE", "version": None}
|
| 99 |
+
version = str(getattr(module, "__version__", "")).strip()
|
| 100 |
+
if not version:
|
| 101 |
+
return {"state": "UNAVAILABLE", "version": None}
|
| 102 |
+
return {"state": "AVAILABLE_UNPROBED", "version": version}
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def _engine_path(status: Mapping[str, Any], engine: str) -> Path | None:
|
| 106 |
+
details = status["engines"][engine]
|
| 107 |
+
raw = details.get("executable_path") if engine == "octave" else details.get("service_executable_path")
|
| 108 |
+
if not raw:
|
| 109 |
+
return None
|
| 110 |
+
path = Path(str(raw))
|
| 111 |
+
return path if path.is_absolute() and path.is_file() else None
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
def preflight(
|
| 115 |
+
*,
|
| 116 |
+
status: Mapping[str, Any] | None = None,
|
| 117 |
+
environ: Mapping[str, str] | None = None,
|
| 118 |
+
os_name: str | None = None,
|
| 119 |
+
mpmath_status: Mapping[str, Any] | None = None,
|
| 120 |
+
) -> dict[str, Any]:
|
| 121 |
+
environment = os.environ if environ is None else environ
|
| 122 |
+
runtime = dict(_adapter.engine_status() if status is None else status)
|
| 123 |
+
host_os = os.name if os_name is None else os_name
|
| 124 |
+
controls = runtime["controls"]
|
| 125 |
+
reasons: list[str] = []
|
| 126 |
+
if host_os != "posix":
|
| 127 |
+
reasons.append("POSIX_RESOURCE_AND_NETWORK_ISOLATION_UNAVAILABLE")
|
| 128 |
+
if not controls.get("network_launcher"):
|
| 129 |
+
reasons.append("NETWORK_NAMESPACE_LAUNCHER_UNAVAILABLE")
|
| 130 |
+
if controls.get("resource_limits") != "PRESENT":
|
| 131 |
+
reasons.append("POSIX_RESOURCE_LIMITS_UNAVAILABLE")
|
| 132 |
+
engines: dict[str, Any] = {}
|
| 133 |
+
for engine in ("octave", "matlab"):
|
| 134 |
+
path = _engine_path(runtime, engine)
|
| 135 |
+
reviewed = environment.get(f"A11OY_{engine.upper()}_LICENSE_REVIEWED") == "1"
|
| 136 |
+
state = runtime["engines"][engine].get("execution_state", "UNAVAILABLE")
|
| 137 |
+
if state != "READY_TO_ATTEMPT" or path is None:
|
| 138 |
+
reasons.append(f"{engine.upper()}_ENGINE_UNAVAILABLE")
|
| 139 |
+
if not reviewed:
|
| 140 |
+
reasons.append(f"{engine.upper()}_LICENSE_REVIEW_UNAVAILABLE")
|
| 141 |
+
engines[engine] = {
|
| 142 |
+
"execution_state": state,
|
| 143 |
+
"executable_sha256": _sha256_file(path) if path is not None else None,
|
| 144 |
+
"license_review": "OPERATOR_REVIEWED" if reviewed else "REVIEW_REQUIRED",
|
| 145 |
+
"offline_license_state": (
|
| 146 |
+
"CONFIGURED_UNVERIFIED"
|
| 147 |
+
if engine == "matlab" and runtime["engines"][engine].get("offline_license_configuration") == "CONFIGURED_UNVERIFIED"
|
| 148 |
+
else ("NOT_APPLICABLE" if engine == "octave" else "UNAVAILABLE")
|
| 149 |
+
),
|
| 150 |
+
}
|
| 151 |
+
reference = dict(_mpmath_status() if mpmath_status is None else mpmath_status)
|
| 152 |
+
if reference.get("state") == "UNAVAILABLE":
|
| 153 |
+
reasons.append("MPMATH_100DP_REFERENCE_UNAVAILABLE")
|
| 154 |
+
core = {
|
| 155 |
+
"schema": PREFLIGHT_SCHEMA,
|
| 156 |
+
"state": "READY_TO_PROBE" if not reasons else "BLOCKED",
|
| 157 |
+
"observed_at_utc": _utc_now(),
|
| 158 |
+
"host": {
|
| 159 |
+
"os_name": host_os,
|
| 160 |
+
"system": platform.system(),
|
| 161 |
+
"machine": platform.machine(),
|
| 162 |
+
"python": platform.python_version(),
|
| 163 |
+
},
|
| 164 |
+
"plan": experiment_plan(),
|
| 165 |
+
"engines": engines,
|
| 166 |
+
"controls": {
|
| 167 |
+
"network_isolation": controls.get("network_isolation", "SOURCE_UNAVAILABLE"),
|
| 168 |
+
"network_launcher_sha256": _sha256_file(Path(controls["network_launcher"])) if controls.get("network_launcher") and Path(controls["network_launcher"]).is_file() else None,
|
| 169 |
+
"resource_limits": controls.get("resource_limits", "SOURCE_UNAVAILABLE"),
|
| 170 |
+
"memory_limit_bytes": controls.get("memory_limit_bytes"),
|
| 171 |
+
"output_limit_bytes": controls.get("output_limit_bytes"),
|
| 172 |
+
"timeout_limit_seconds": controls.get("timeout_limit_seconds"),
|
| 173 |
+
},
|
| 174 |
+
"reference": {**reference, "precision_decimal_digits": 100},
|
| 175 |
+
"blockers": sorted(set(reasons)),
|
| 176 |
+
"engine_invocations": 0,
|
| 177 |
+
"result_rows": 0,
|
| 178 |
+
"network_denial_evidence": "NOT_EVALUATED",
|
| 179 |
+
"substrate_evidence": "UNKNOWN",
|
| 180 |
+
"interpretation_guard": "A ready preflight is permission to probe, not an engine result or agreement claim.",
|
| 181 |
+
**ZERO_UPLIFT,
|
| 182 |
+
}
|
| 183 |
+
return {**core, "receipt_sha256": _adapter.digest_json(core)}
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def _isolation_probe(status: Mapping[str, Any]) -> dict[str, Any]:
|
| 187 |
+
if os.name != "posix" or not _ISOLATION_HELPER.is_file():
|
| 188 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_EVIDENCE_UNAVAILABLE")
|
| 189 |
+
launcher = status["controls"].get("network_launcher")
|
| 190 |
+
if not launcher:
|
| 191 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_EVIDENCE_UNAVAILABLE")
|
| 192 |
+
parent_namespace = os.readlink("/proc/self/ns/net")
|
| 193 |
+
with tempfile.TemporaryDirectory(prefix="a11oy-numerics-netprobe-") as tmp:
|
| 194 |
+
evidence_path = Path(tmp) / "network-evidence.json"
|
| 195 |
+
command = [launcher, "--net", "--", sys.executable, "-I", str(_ISOLATION_HELPER), str(evidence_path)]
|
| 196 |
+
try:
|
| 197 |
+
completed = subprocess.run(
|
| 198 |
+
command,
|
| 199 |
+
cwd=tmp,
|
| 200 |
+
env=_child_env(Path(tmp)),
|
| 201 |
+
stdin=subprocess.DEVNULL,
|
| 202 |
+
stdout=subprocess.DEVNULL,
|
| 203 |
+
stderr=subprocess.DEVNULL,
|
| 204 |
+
shell=False,
|
| 205 |
+
timeout=5,
|
| 206 |
+
check=False,
|
| 207 |
+
preexec_fn=_adapter._preexec_limits(5),
|
| 208 |
+
)
|
| 209 |
+
except (OSError, subprocess.TimeoutExpired) as exc:
|
| 210 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_PROBE_FAILED") from exc
|
| 211 |
+
if completed.returncode != 0 or not evidence_path.is_file() or evidence_path.stat().st_size > 16 * 1024:
|
| 212 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_PROBE_FAILED")
|
| 213 |
+
try:
|
| 214 |
+
child = json.loads(evidence_path.read_text(encoding="utf-8"))
|
| 215 |
+
except (OSError, json.JSONDecodeError) as exc:
|
| 216 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_EVIDENCE_INVALID") from exc
|
| 217 |
+
if child.get("schema") != "szl.numerics.network-namespace-evidence/v1":
|
| 218 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_EVIDENCE_INVALID")
|
| 219 |
+
if child.get("network_operations_performed") != 0 or child.get("network_namespace") == parent_namespace:
|
| 220 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_NOT_SEPARATE")
|
| 221 |
+
if child.get("interfaces") != ["lo"] or child.get("loopback_operstate") not in ("down", "unknown"):
|
| 222 |
+
raise ExperimentUnavailable("NETWORK_NAMESPACE_NOT_DENY_BY_DEFAULT")
|
| 223 |
+
core = {
|
| 224 |
+
**child,
|
| 225 |
+
"state": "DENIED",
|
| 226 |
+
"parent_network_namespace": parent_namespace,
|
| 227 |
+
"launcher_sha256": _sha256_file(Path(launcher)),
|
| 228 |
+
"helper_sha256": _sha256_file(_ISOLATION_HELPER),
|
| 229 |
+
}
|
| 230 |
+
return {**core, "evidence_sha256": _adapter.digest_json(core)}
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def _probe_engine_version(engine: str, status: Mapping[str, Any]) -> dict[str, Any]:
|
| 234 |
+
path = _engine_path(status, engine)
|
| 235 |
+
launcher = status["controls"].get("network_launcher")
|
| 236 |
+
if path is None or not launcher:
|
| 237 |
+
raise ExperimentUnavailable(f"{engine.upper()}_VERSION_PROBE_UNAVAILABLE")
|
| 238 |
+
if engine == "octave":
|
| 239 |
+
command = [launcher, "--net", "--", str(path), "--version"]
|
| 240 |
+
else:
|
| 241 |
+
command = [launcher, "--net", "--", str(path), "--version"]
|
| 242 |
+
try:
|
| 243 |
+
with tempfile.TemporaryDirectory(prefix=f"a11oy-numerics-{engine}-version-") as tmp:
|
| 244 |
+
completed = subprocess.run(
|
| 245 |
+
command,
|
| 246 |
+
cwd=tmp,
|
| 247 |
+
env=_child_env(Path(tmp)),
|
| 248 |
+
stdin=subprocess.DEVNULL,
|
| 249 |
+
stdout=subprocess.PIPE,
|
| 250 |
+
stderr=subprocess.STDOUT,
|
| 251 |
+
shell=False,
|
| 252 |
+
timeout=8,
|
| 253 |
+
check=False,
|
| 254 |
+
preexec_fn=_adapter._preexec_limits(8),
|
| 255 |
+
)
|
| 256 |
+
except (OSError, subprocess.TimeoutExpired) as exc:
|
| 257 |
+
raise ExperimentUnavailable(f"{engine.upper()}_VERSION_PROBE_FAILED") from exc
|
| 258 |
+
output = completed.stdout or b""
|
| 259 |
+
if completed.returncode != 0 or not output or len(output) > _MAX_VERSION_OUTPUT_BYTES:
|
| 260 |
+
raise ExperimentUnavailable(f"{engine.upper()}_VERSION_PROBE_FAILED")
|
| 261 |
+
try:
|
| 262 |
+
lines = [line.strip() for line in output.decode("utf-8").splitlines() if line.strip()]
|
| 263 |
+
except UnicodeDecodeError as exc:
|
| 264 |
+
raise ExperimentUnavailable(f"{engine.upper()}_VERSION_PROBE_INVALID") from exc
|
| 265 |
+
if not lines or len(lines[0]) > 120:
|
| 266 |
+
raise ExperimentUnavailable(f"{engine.upper()}_VERSION_PROBE_INVALID")
|
| 267 |
+
return {
|
| 268 |
+
"version": lines[0],
|
| 269 |
+
"version_evidence_sha256": _sha256_bytes(output),
|
| 270 |
+
"executable_sha256": _sha256_file(path),
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
def _iter_cases() -> Iterable[dict[str, Any]]:
|
| 275 |
+
offset = 0
|
| 276 |
+
total = experiment_plan()["case_counts"]["total"]
|
| 277 |
+
while offset < total:
|
| 278 |
+
page = _dataset.list_cases(offset=offset, limit=min(100, total - offset))
|
| 279 |
+
for descriptor in page["items"]:
|
| 280 |
+
yield _dataset.get_case(descriptor["case_id"])
|
| 281 |
+
offset += len(page["items"])
|
| 282 |
+
if not page["items"]:
|
| 283 |
+
raise ExperimentUnavailable("PREREGISTERED_CASE_ENUMERATION_INCOMPLETE")
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
def _reference(case: Mapping[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
|
| 287 |
+
try:
|
| 288 |
+
mp = importlib.import_module("mpmath")
|
| 289 |
+
except ImportError as exc:
|
| 290 |
+
raise ExperimentUnavailable("MPMATH_100DP_REFERENCE_UNAVAILABLE") from exc
|
| 291 |
+
mp.mp.dps = 100
|
| 292 |
+
matrix = mp.matrix([[mp.mpf(format(value, ".17g")) for value in row] for row in case["request"]["inputs"]["matrix"]])
|
| 293 |
+
operation = case["operation"]
|
| 294 |
+
if operation == "SYMMETRIC_EIGENVALUES":
|
| 295 |
+
computed = mp.eigsy(matrix, eigvals_only=True)
|
| 296 |
+
values_mp = [computed[index] for index in range(len(computed))]
|
| 297 |
+
else:
|
| 298 |
+
rhs = mp.matrix([mp.mpf(format(value, ".17g")) for value in case["request"]["inputs"]["rhs"]])
|
| 299 |
+
computed = mp.lu_solve(matrix, rhs)
|
| 300 |
+
values_mp = [computed[index] for index in range(len(computed))]
|
| 301 |
+
decimal_values = [mp.nstr(value, 105, strip_zeros=False) for value in values_mp]
|
| 302 |
+
evidence_core = {
|
| 303 |
+
"schema": REFERENCE_SCHEMA,
|
| 304 |
+
"case_id": case["case_id"],
|
| 305 |
+
"fixture_sha256": case["fixture_sha256"],
|
| 306 |
+
"implementation": "PYTHON_MPMATH_100DP",
|
| 307 |
+
"mpmath_version": str(mp.__version__),
|
| 308 |
+
"precision_decimal_digits": 100,
|
| 309 |
+
"decimal_values": decimal_values,
|
| 310 |
+
}
|
| 311 |
+
evidence_sha256 = _adapter.digest_json(evidence_core)
|
| 312 |
+
return (
|
| 313 |
+
{
|
| 314 |
+
"state": "MEASURED",
|
| 315 |
+
"implementation": "PYTHON_MPMATH_100DP",
|
| 316 |
+
"values": [float(value) for value in values_mp],
|
| 317 |
+
"evidence_sha256": evidence_sha256,
|
| 318 |
+
},
|
| 319 |
+
{**evidence_core, "evidence_sha256": evidence_sha256},
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def _child_cpu_snapshot() -> tuple[int | None, int | None]:
|
| 324 |
+
try:
|
| 325 |
+
import resource
|
| 326 |
+
|
| 327 |
+
usage = resource.getrusage(resource.RUSAGE_CHILDREN)
|
| 328 |
+
except (ImportError, OSError):
|
| 329 |
+
return None, None
|
| 330 |
+
return int(usage.ru_utime * 1_000_000_000), int(usage.ru_stime * 1_000_000_000)
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
def _observe_case(
|
| 334 |
+
engine: str,
|
| 335 |
+
case: Mapping[str, Any],
|
| 336 |
+
version: Mapping[str, Any],
|
| 337 |
+
isolation: Mapping[str, Any],
|
| 338 |
+
) -> tuple[dict[str, Any], dict[str, Any]]:
|
| 339 |
+
request = case["request"]
|
| 340 |
+
before_user, before_system = _child_cpu_snapshot()
|
| 341 |
+
started = time.perf_counter_ns()
|
| 342 |
+
result = _adapter.run_engine(engine, request)
|
| 343 |
+
elapsed = time.perf_counter_ns() - started
|
| 344 |
+
after_user, after_system = _child_cpu_snapshot()
|
| 345 |
+
user_ns = after_user - before_user if before_user is not None and after_user is not None else None
|
| 346 |
+
system_ns = after_system - before_system if before_system is not None and after_system is not None else None
|
| 347 |
+
reference, reference_evidence = _reference(case)
|
| 348 |
+
outcome = (
|
| 349 |
+
{"state": "RESULT", "values": result["values"]}
|
| 350 |
+
if result["state"] == "RESULT"
|
| 351 |
+
else {"state": "UNAVAILABLE", "reason": str(result.get("reason") or "ENGINE_UNAVAILABLE")[:160]}
|
| 352 |
+
)
|
| 353 |
+
# Keep the append-ledger identifier inside the strict 96-character ID
|
| 354 |
+
# boundary without sacrificing uniqueness or reproducibility. The case
|
| 355 |
+
# request digest is frozen by the preregistration.
|
| 356 |
+
run_id = f"{engine}-{str(case['case_id'])[:40]}-{str(case['request_sha256'])[:16]}"
|
| 357 |
+
payload = {
|
| 358 |
+
"schema": _dataset.INGEST_SCHEMA,
|
| 359 |
+
"run_id": run_id,
|
| 360 |
+
"case_id": case["case_id"],
|
| 361 |
+
"engine": engine,
|
| 362 |
+
"outcome": outcome,
|
| 363 |
+
"engine_evidence": {
|
| 364 |
+
**version,
|
| 365 |
+
"license_state": "OPERATOR_REVIEWED",
|
| 366 |
+
"offline_license_state": "CONFIGURED" if engine == "matlab" else "NOT_APPLICABLE",
|
| 367 |
+
},
|
| 368 |
+
"containment": {"network_state": "DENIED", "evidence_sha256": isolation["evidence_sha256"]},
|
| 369 |
+
"resources": {
|
| 370 |
+
"wall_time_ns": elapsed,
|
| 371 |
+
"child_user_cpu_ns": user_ns,
|
| 372 |
+
"child_system_cpu_ns": system_ns,
|
| 373 |
+
"peak_resident_bytes": None,
|
| 374 |
+
"request_bytes": len(_adapter.canonical_json(request)),
|
| 375 |
+
"response_bytes": len(_adapter.canonical_json(result)),
|
| 376 |
+
"log_bytes": None,
|
| 377 |
+
},
|
| 378 |
+
"reference": reference,
|
| 379 |
+
"observed_at_utc": _utc_now(),
|
| 380 |
+
}
|
| 381 |
+
return _dataset.ingest_result(payload), reference_evidence
|
| 382 |
+
|
| 383 |
+
|
| 384 |
+
def _write_json(path: Path, value: Mapping[str, Any]) -> None:
|
| 385 |
+
encoded = json.dumps(value, indent=2, sort_keys=True, ensure_ascii=False) + "\n"
|
| 386 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 387 |
+
temporary = path.with_suffix(path.suffix + ".tmp")
|
| 388 |
+
with temporary.open("w", encoding="utf-8", newline="\n") as handle:
|
| 389 |
+
handle.write(encoded)
|
| 390 |
+
handle.flush()
|
| 391 |
+
os.fsync(handle.fileno())
|
| 392 |
+
os.replace(temporary, path)
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
def run_preregistered(*, execute_all: bool = False) -> dict[str, Any]:
|
| 396 |
+
check = preflight()
|
| 397 |
+
core: dict[str, Any] = {
|
| 398 |
+
"schema": EXPERIMENT_SCHEMA,
|
| 399 |
+
"state": "BLOCKED" if check["state"] == "BLOCKED" else ("READY_NOT_EXECUTED" if not execute_all else "RUNNING"),
|
| 400 |
+
"observed_at_utc": _utc_now(),
|
| 401 |
+
"plan": check["plan"],
|
| 402 |
+
"preflight_receipt_sha256": check["receipt_sha256"],
|
| 403 |
+
"preflight": check,
|
| 404 |
+
"engine_invocations": 0,
|
| 405 |
+
"engine_invocation_semantics": "ADAPTER_CALLS; CHILD_PROCESS_STARTS_NOT_INDEPENDENTLY_COUNTED",
|
| 406 |
+
"result_rows": 0,
|
| 407 |
+
"pair_outcomes": {"MATCH": 0, "CONFLICT": 0, "UNAVAILABLE": 0},
|
| 408 |
+
"reference_rows": 0,
|
| 409 |
+
"substrate_evidence": "UNKNOWN",
|
| 410 |
+
"interpretation_guard": "MATCH is case-scoped numerical agreement, not proof or a general engine-quality claim.",
|
| 411 |
+
**ZERO_UPLIFT,
|
| 412 |
+
}
|
| 413 |
+
if check["state"] == "BLOCKED" or not execute_all:
|
| 414 |
+
return {**core, "receipt_sha256": _adapter.digest_json(core)}
|
| 415 |
+
|
| 416 |
+
runtime = _adapter.engine_status()
|
| 417 |
+
try:
|
| 418 |
+
isolation = _isolation_probe(runtime)
|
| 419 |
+
versions = {engine: _probe_engine_version(engine, runtime) for engine in ("octave", "matlab")}
|
| 420 |
+
except ExperimentUnavailable as exc:
|
| 421 |
+
core.update({"state": "BLOCKED", "blocker": str(exc)})
|
| 422 |
+
return {**core, "receipt_sha256": _adapter.digest_json(core)}
|
| 423 |
+
|
| 424 |
+
reference_chain: list[dict[str, Any]] = []
|
| 425 |
+
outcomes = {"MATCH": 0, "CONFLICT": 0, "UNAVAILABLE": 0}
|
| 426 |
+
invocations = 0
|
| 427 |
+
result_rows = 0
|
| 428 |
+
for case in _iter_cases():
|
| 429 |
+
pair: list[dict[str, Any]] = []
|
| 430 |
+
for engine in ("octave", "matlab"):
|
| 431 |
+
row, reference_evidence = _observe_case(engine, case, versions[engine], isolation)
|
| 432 |
+
invocations += 1
|
| 433 |
+
result_rows += 1
|
| 434 |
+
pair.append(row)
|
| 435 |
+
if not reference_chain or reference_chain[-1]["case_id"] != case["case_id"]:
|
| 436 |
+
reference_chain.append(reference_evidence)
|
| 437 |
+
final_state = pair[-1]["comparison_state"] if pair[-1]["comparison_state"] in ("MATCH", "CONFLICT") else "UNAVAILABLE"
|
| 438 |
+
outcomes[final_state] += 1
|
| 439 |
+
|
| 440 |
+
complete = (
|
| 441 |
+
result_rows == core["plan"]["planned_engine_runs"]
|
| 442 |
+
and sum(outcomes.values()) == core["plan"]["case_counts"]["total"]
|
| 443 |
+
and outcomes["UNAVAILABLE"] == 0
|
| 444 |
+
)
|
| 445 |
+
core.update({
|
| 446 |
+
"state": "COMPLETE" if complete else "INCOMPLETE",
|
| 447 |
+
"engine_invocations": invocations,
|
| 448 |
+
"result_rows": result_rows,
|
| 449 |
+
"pair_outcomes": outcomes,
|
| 450 |
+
"reference_rows": len(reference_chain),
|
| 451 |
+
"reference_evidence": reference_chain,
|
| 452 |
+
"reference_chain_sha256": _adapter.digest_json(reference_chain),
|
| 453 |
+
"network_denial_evidence_sha256": isolation["evidence_sha256"],
|
| 454 |
+
"engine_versions": versions,
|
| 455 |
+
"substrate_evidence": "UNKNOWN",
|
| 456 |
+
})
|
| 457 |
+
return {**core, "receipt_sha256": _adapter.digest_json(core)}
|
| 458 |
+
|
| 459 |
+
|
| 460 |
+
def main(argv: list[str] | None = None) -> int:
|
| 461 |
+
parser = argparse.ArgumentParser(description="Run or preflight the frozen MATLAB/Octave comparison")
|
| 462 |
+
parser.add_argument("--execute-all", action="store_true", help="run all 1,328 cases on both engines after every gate passes")
|
| 463 |
+
parser.add_argument("--output", type=Path, required=True, help="write one atomic JSON experiment receipt")
|
| 464 |
+
args = parser.parse_args(argv)
|
| 465 |
+
receipt = run_preregistered(execute_all=args.execute_all)
|
| 466 |
+
_write_json(args.output, receipt)
|
| 467 |
+
print(json.dumps({"state": receipt["state"], "receipt_sha256": receipt["receipt_sha256"]}, sort_keys=True))
|
| 468 |
+
return 0 if receipt["state"] in ("READY_NOT_EXECUTED", "COMPLETE") else 2
|
| 469 |
+
|
| 470 |
+
|
| 471 |
+
if __name__ == "__main__":
|
| 472 |
+
raise SystemExit(main())
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
__all__ = [
|
| 476 |
+
"EXPERIMENT_SCHEMA",
|
| 477 |
+
"PREFLIGHT_SCHEMA",
|
| 478 |
+
"ExperimentUnavailable",
|
| 479 |
+
"experiment_plan",
|
| 480 |
+
"preflight",
|
| 481 |
+
"run_preregistered",
|
| 482 |
+
]
|
|
@@ -0,0 +1,463 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Bounded, fail-closed HTTP JSON transport for provider control planes.
|
| 2 |
+
|
| 3 |
+
This module is deliberately independent from the provider registry so every
|
| 4 |
+
provider adapter can share one outbound-security boundary. It does not log
|
| 5 |
+
URLs, headers, request bodies, response bodies, or exception text. Failures
|
| 6 |
+
return stable error codes and never synthesize a document.
|
| 7 |
+
|
| 8 |
+
Public destinations are allowed by default. Operator-controlled self-hosted
|
| 9 |
+
destinations (loopback, RFC1918/ULA, and CGNAT/Tailscale space) require the
|
| 10 |
+
caller to pass ``allow_private=True`` explicitly. Link-local destinations,
|
| 11 |
+
including cloud metadata ranges, remain forbidden even with that opt-in.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
from __future__ import annotations
|
| 15 |
+
|
| 16 |
+
import http.client
|
| 17 |
+
import ipaddress
|
| 18 |
+
import json
|
| 19 |
+
import math
|
| 20 |
+
import queue
|
| 21 |
+
import socket
|
| 22 |
+
import ssl
|
| 23 |
+
import threading
|
| 24 |
+
import time
|
| 25 |
+
from dataclasses import dataclass
|
| 26 |
+
from typing import Any, Mapping
|
| 27 |
+
from urllib.parse import quote, urljoin, urlsplit
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
DEFAULT_TIMEOUT_S = 4.0
|
| 31 |
+
MAX_TIMEOUT_S = 120.0
|
| 32 |
+
DEFAULT_MAX_RESPONSE_BYTES = 1_048_576
|
| 33 |
+
MAX_RESPONSE_BYTES = 8_388_608
|
| 34 |
+
MAX_REQUEST_BYTES = 8_388_608
|
| 35 |
+
DEFAULT_MAX_REDIRECTS = 2
|
| 36 |
+
MAX_REDIRECTS = 5
|
| 37 |
+
MAX_LOCATION_BYTES = 8_192
|
| 38 |
+
|
| 39 |
+
_REDIRECT_STATUSES = frozenset({301, 302, 303, 307, 308})
|
| 40 |
+
_SENSITIVE_REDIRECT_HEADERS = frozenset(
|
| 41 |
+
{"authorization", "proxy-authorization", "cookie"}
|
| 42 |
+
)
|
| 43 |
+
_RESERVED_REQUEST_HEADERS = frozenset(
|
| 44 |
+
{"host", "content-length", "transfer-encoding", "connection"}
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
@dataclass(frozen=True)
|
| 49 |
+
class _Target:
|
| 50 |
+
"""A parsed target pinned to the addresses validated for this hop."""
|
| 51 |
+
|
| 52 |
+
url: str
|
| 53 |
+
scheme: str
|
| 54 |
+
hostname: str
|
| 55 |
+
port: int
|
| 56 |
+
request_target: str
|
| 57 |
+
host_header: str
|
| 58 |
+
origin: tuple[str, str, int]
|
| 59 |
+
addresses: tuple[str, ...]
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class _PinnedHTTPSConnection(http.client.HTTPSConnection):
|
| 63 |
+
"""HTTPS connection that uses a validated IP while verifying the URL host."""
|
| 64 |
+
|
| 65 |
+
def __init__(
|
| 66 |
+
self,
|
| 67 |
+
hostname: str,
|
| 68 |
+
address: str,
|
| 69 |
+
port: int,
|
| 70 |
+
*,
|
| 71 |
+
timeout: float,
|
| 72 |
+
context: ssl.SSLContext,
|
| 73 |
+
) -> None:
|
| 74 |
+
super().__init__(hostname, port=port, timeout=timeout, context=context)
|
| 75 |
+
self._validated_address = address
|
| 76 |
+
|
| 77 |
+
def connect(self) -> None:
|
| 78 |
+
self.sock = socket.create_connection(
|
| 79 |
+
(self._validated_address, self.port),
|
| 80 |
+
self.timeout,
|
| 81 |
+
self.source_address,
|
| 82 |
+
)
|
| 83 |
+
self.sock = self._context.wrap_socket(self.sock, server_hostname=self.host)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def _remaining(deadline: float) -> float:
|
| 87 |
+
return max(0.0, deadline - time.monotonic())
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _contains_control(value: str) -> bool:
|
| 91 |
+
return any(ord(ch) < 32 or ord(ch) == 127 for ch in value)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def _resolve_bounded(hostname: str, port: int, deadline: float) -> tuple[Any, str | None]:
|
| 95 |
+
"""Run DNS in a daemon thread so a resolver stall cannot exceed the call budget."""
|
| 96 |
+
|
| 97 |
+
remaining = _remaining(deadline)
|
| 98 |
+
if remaining <= 0:
|
| 99 |
+
return None, "TIMEOUT"
|
| 100 |
+
|
| 101 |
+
result: queue.Queue[tuple[Any, str | None]] = queue.Queue(maxsize=1)
|
| 102 |
+
|
| 103 |
+
def _worker() -> None:
|
| 104 |
+
try:
|
| 105 |
+
infos = socket.getaddrinfo(
|
| 106 |
+
hostname,
|
| 107 |
+
port,
|
| 108 |
+
family=socket.AF_UNSPEC,
|
| 109 |
+
type=socket.SOCK_STREAM,
|
| 110 |
+
)
|
| 111 |
+
item: tuple[Any, str | None] = (infos, None)
|
| 112 |
+
except Exception: # DNS details can contain a secret-bearing URL on some stacks.
|
| 113 |
+
item = (None, "DNS_RESOLUTION_FAILED")
|
| 114 |
+
try:
|
| 115 |
+
result.put_nowait(item)
|
| 116 |
+
except queue.Full:
|
| 117 |
+
pass
|
| 118 |
+
|
| 119 |
+
threading.Thread(target=_worker, name="provider-dns", daemon=True).start()
|
| 120 |
+
try:
|
| 121 |
+
return result.get(timeout=remaining)
|
| 122 |
+
except queue.Empty:
|
| 123 |
+
return None, "TIMEOUT"
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def _classify_address(value: str, *, allow_private: bool) -> str | None:
|
| 127 |
+
try:
|
| 128 |
+
address = ipaddress.ip_address(value)
|
| 129 |
+
except ValueError:
|
| 130 |
+
return "DNS_INVALID_ADDRESS"
|
| 131 |
+
|
| 132 |
+
# Apply the IPv4 policy to IPv4-mapped IPv6 values as well.
|
| 133 |
+
if isinstance(address, ipaddress.IPv6Address) and address.ipv4_mapped:
|
| 134 |
+
address = address.ipv4_mapped
|
| 135 |
+
|
| 136 |
+
# Link-local is always denied: it includes the common cloud metadata path.
|
| 137 |
+
# ``ipaddress`` also classifies IPv6 loopback (``::1``) as reserved on some
|
| 138 |
+
# Python versions. Loopback is an explicitly supported self-hosted target,
|
| 139 |
+
# so do not let that implementation detail override ``allow_private=True``.
|
| 140 |
+
if (
|
| 141 |
+
address.is_unspecified
|
| 142 |
+
or address.is_multicast
|
| 143 |
+
or address.is_link_local
|
| 144 |
+
or (address.is_reserved and not address.is_loopback)
|
| 145 |
+
):
|
| 146 |
+
return "DESTINATION_FORBIDDEN"
|
| 147 |
+
|
| 148 |
+
# is_global=False covers loopback, RFC1918/ULA, and CGNAT/Tailscale space.
|
| 149 |
+
if not address.is_global and not allow_private:
|
| 150 |
+
return "PRIVATE_DESTINATION_REQUIRES_OPT_IN"
|
| 151 |
+
return None
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def _validate_target(
|
| 155 |
+
url: str,
|
| 156 |
+
*,
|
| 157 |
+
allow_private: bool,
|
| 158 |
+
deadline: float,
|
| 159 |
+
) -> tuple[_Target | None, str | None]:
|
| 160 |
+
if not isinstance(url, str) or not url or _contains_control(url):
|
| 161 |
+
return None, "INVALID_URL"
|
| 162 |
+
try:
|
| 163 |
+
parts = urlsplit(url)
|
| 164 |
+
except (TypeError, ValueError):
|
| 165 |
+
return None, "INVALID_URL"
|
| 166 |
+
|
| 167 |
+
scheme = parts.scheme.lower()
|
| 168 |
+
if scheme not in {"http", "https"}:
|
| 169 |
+
return None, "INVALID_URL_SCHEME"
|
| 170 |
+
if parts.username is not None or parts.password is not None:
|
| 171 |
+
return None, "URL_CREDENTIALS_FORBIDDEN"
|
| 172 |
+
if parts.fragment:
|
| 173 |
+
return None, "URL_FRAGMENT_FORBIDDEN"
|
| 174 |
+
if not parts.hostname or "\\" in parts.netloc:
|
| 175 |
+
return None, "INVALID_URL"
|
| 176 |
+
|
| 177 |
+
try:
|
| 178 |
+
hostname = parts.hostname.encode("idna").decode("ascii").lower()
|
| 179 |
+
port = parts.port or (443 if scheme == "https" else 80)
|
| 180 |
+
except (UnicodeError, ValueError):
|
| 181 |
+
return None, "INVALID_URL"
|
| 182 |
+
|
| 183 |
+
infos, resolve_error = _resolve_bounded(hostname, port, deadline)
|
| 184 |
+
if resolve_error:
|
| 185 |
+
return None, resolve_error
|
| 186 |
+
|
| 187 |
+
addresses: list[str] = []
|
| 188 |
+
for family, _socktype, _proto, _canonname, sockaddr in infos or []:
|
| 189 |
+
if family not in {socket.AF_INET, socket.AF_INET6} or not sockaddr:
|
| 190 |
+
continue
|
| 191 |
+
address = str(sockaddr[0])
|
| 192 |
+
policy_error = _classify_address(address, allow_private=allow_private)
|
| 193 |
+
if policy_error:
|
| 194 |
+
# Reject a mixed public/private DNS answer; never select only its safe half.
|
| 195 |
+
return None, policy_error
|
| 196 |
+
if address not in addresses:
|
| 197 |
+
addresses.append(address)
|
| 198 |
+
if not addresses:
|
| 199 |
+
return None, "DNS_NO_ADDRESSES"
|
| 200 |
+
|
| 201 |
+
path = quote(parts.path or "/", safe="/%:@-._~!$&'()*+,;=")
|
| 202 |
+
query = quote(parts.query, safe="/%?:@-._~!$&'()*+,;=")
|
| 203 |
+
request_target = path + (("?" + query) if query else "")
|
| 204 |
+
default_port = 443 if scheme == "https" else 80
|
| 205 |
+
display_host = "[" + hostname + "]" if ":" in hostname else hostname
|
| 206 |
+
host_header = display_host if port == default_port else f"{display_host}:{port}"
|
| 207 |
+
return (
|
| 208 |
+
_Target(
|
| 209 |
+
url=url,
|
| 210 |
+
scheme=scheme,
|
| 211 |
+
hostname=hostname,
|
| 212 |
+
port=port,
|
| 213 |
+
request_target=request_target,
|
| 214 |
+
host_header=host_header,
|
| 215 |
+
origin=(scheme, hostname, port),
|
| 216 |
+
addresses=tuple(addresses),
|
| 217 |
+
),
|
| 218 |
+
None,
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
def _prepare_headers(headers: Mapping[str, str] | None) -> tuple[dict[str, str] | None, str | None]:
|
| 223 |
+
prepared = {
|
| 224 |
+
"Accept": "application/json",
|
| 225 |
+
"User-Agent": "a11oy-provider-http/1.0",
|
| 226 |
+
}
|
| 227 |
+
if headers is None:
|
| 228 |
+
return prepared, None
|
| 229 |
+
if not isinstance(headers, Mapping):
|
| 230 |
+
return None, "INVALID_HEADERS"
|
| 231 |
+
for name, value in headers.items():
|
| 232 |
+
if not isinstance(name, str) or not isinstance(value, str):
|
| 233 |
+
return None, "INVALID_HEADERS"
|
| 234 |
+
normalized = name.strip().lower()
|
| 235 |
+
if (
|
| 236 |
+
not normalized
|
| 237 |
+
or normalized in _RESERVED_REQUEST_HEADERS
|
| 238 |
+
or ":" in name
|
| 239 |
+
or _contains_control(name)
|
| 240 |
+
or _contains_control(value)
|
| 241 |
+
):
|
| 242 |
+
return None, "INVALID_HEADERS"
|
| 243 |
+
prepared[name] = value
|
| 244 |
+
return prepared, None
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
def _request_once(
|
| 248 |
+
target: _Target,
|
| 249 |
+
*,
|
| 250 |
+
method: str,
|
| 251 |
+
body: bytes | None,
|
| 252 |
+
headers: Mapping[str, str],
|
| 253 |
+
deadline: float,
|
| 254 |
+
) -> tuple[http.client.HTTPResponse | None, http.client.HTTPConnection | None, str | None]:
|
| 255 |
+
last_error = "NETWORK_FAILURE"
|
| 256 |
+
for address in target.addresses:
|
| 257 |
+
remaining = _remaining(deadline)
|
| 258 |
+
if remaining <= 0:
|
| 259 |
+
return None, None, "TIMEOUT"
|
| 260 |
+
connection: http.client.HTTPConnection
|
| 261 |
+
try:
|
| 262 |
+
if target.scheme == "https":
|
| 263 |
+
connection = _PinnedHTTPSConnection(
|
| 264 |
+
target.hostname,
|
| 265 |
+
address,
|
| 266 |
+
target.port,
|
| 267 |
+
timeout=remaining,
|
| 268 |
+
context=ssl.create_default_context(),
|
| 269 |
+
)
|
| 270 |
+
else:
|
| 271 |
+
connection = http.client.HTTPConnection(
|
| 272 |
+
address,
|
| 273 |
+
port=target.port,
|
| 274 |
+
timeout=remaining,
|
| 275 |
+
)
|
| 276 |
+
hop_headers = dict(headers)
|
| 277 |
+
hop_headers["Host"] = target.host_header
|
| 278 |
+
connection.request(
|
| 279 |
+
method,
|
| 280 |
+
target.request_target,
|
| 281 |
+
body=body,
|
| 282 |
+
headers=hop_headers,
|
| 283 |
+
)
|
| 284 |
+
response_budget = _remaining(deadline)
|
| 285 |
+
if response_budget <= 0:
|
| 286 |
+
connection.close()
|
| 287 |
+
return None, None, "TIMEOUT"
|
| 288 |
+
if connection.sock is not None:
|
| 289 |
+
connection.sock.settimeout(response_budget)
|
| 290 |
+
return connection.getresponse(), connection, None
|
| 291 |
+
except (TimeoutError, socket.timeout):
|
| 292 |
+
last_error = "TIMEOUT"
|
| 293 |
+
except ssl.SSLError:
|
| 294 |
+
last_error = "TLS_FAILURE"
|
| 295 |
+
except Exception:
|
| 296 |
+
last_error = "NETWORK_FAILURE"
|
| 297 |
+
try:
|
| 298 |
+
connection.close()
|
| 299 |
+
except Exception:
|
| 300 |
+
pass
|
| 301 |
+
return None, None, last_error
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def http_json(
|
| 305 |
+
url: str,
|
| 306 |
+
*,
|
| 307 |
+
method: str = "GET",
|
| 308 |
+
body: bytes | None = None,
|
| 309 |
+
headers: Mapping[str, str] | None = None,
|
| 310 |
+
timeout: float = DEFAULT_TIMEOUT_S,
|
| 311 |
+
max_response_bytes: int = DEFAULT_MAX_RESPONSE_BYTES,
|
| 312 |
+
max_redirects: int = DEFAULT_MAX_REDIRECTS,
|
| 313 |
+
allow_private: bool = False,
|
| 314 |
+
) -> tuple[Any, str | None]:
|
| 315 |
+
"""Fetch one JSON document through the bounded provider transport.
|
| 316 |
+
|
| 317 |
+
Returns ``(document, None)`` only after a real 2xx response containing valid
|
| 318 |
+
UTF-8 JSON. Every failure returns ``(None, STABLE_ERROR_CODE)``. The caller
|
| 319 |
+
must set ``allow_private=True`` only for an operator-controlled self-hosted
|
| 320 |
+
base URL (for example local Ollama at ``127.0.0.1:11434``).
|
| 321 |
+
"""
|
| 322 |
+
|
| 323 |
+
method = method.upper() if isinstance(method, str) else ""
|
| 324 |
+
if method not in {"GET", "POST"}:
|
| 325 |
+
return None, "INVALID_METHOD"
|
| 326 |
+
# Private routing is an explicit capability grant, not a truthy option.
|
| 327 |
+
if not isinstance(allow_private, bool):
|
| 328 |
+
return None, "INVALID_PRIVATE_OPT_IN"
|
| 329 |
+
if body is not None and not isinstance(body, (bytes, bytearray)):
|
| 330 |
+
return None, "INVALID_BODY"
|
| 331 |
+
body_bytes = bytes(body) if body is not None else None
|
| 332 |
+
if body_bytes is not None and len(body_bytes) > MAX_REQUEST_BYTES:
|
| 333 |
+
return None, "REQUEST_TOO_LARGE"
|
| 334 |
+
try:
|
| 335 |
+
timeout_value = float(timeout)
|
| 336 |
+
except (TypeError, ValueError):
|
| 337 |
+
return None, "INVALID_TIMEOUT"
|
| 338 |
+
if (
|
| 339 |
+
isinstance(timeout, bool)
|
| 340 |
+
or not math.isfinite(timeout_value)
|
| 341 |
+
or timeout_value <= 0
|
| 342 |
+
or timeout_value > MAX_TIMEOUT_S
|
| 343 |
+
):
|
| 344 |
+
return None, "INVALID_TIMEOUT"
|
| 345 |
+
if (
|
| 346 |
+
isinstance(max_response_bytes, bool)
|
| 347 |
+
or not isinstance(max_response_bytes, int)
|
| 348 |
+
or max_response_bytes <= 0
|
| 349 |
+
or max_response_bytes > MAX_RESPONSE_BYTES
|
| 350 |
+
):
|
| 351 |
+
return None, "INVALID_RESPONSE_LIMIT"
|
| 352 |
+
if (
|
| 353 |
+
isinstance(max_redirects, bool)
|
| 354 |
+
or not isinstance(max_redirects, int)
|
| 355 |
+
or max_redirects < 0
|
| 356 |
+
or max_redirects > MAX_REDIRECTS
|
| 357 |
+
):
|
| 358 |
+
return None, "INVALID_REDIRECT_LIMIT"
|
| 359 |
+
|
| 360 |
+
active_headers, header_error = _prepare_headers(headers)
|
| 361 |
+
if header_error or active_headers is None:
|
| 362 |
+
return None, header_error or "INVALID_HEADERS"
|
| 363 |
+
if body_bytes is not None and not any(k.lower() == "content-type" for k in active_headers):
|
| 364 |
+
active_headers["Content-Type"] = "application/json"
|
| 365 |
+
|
| 366 |
+
deadline = time.monotonic() + timeout_value
|
| 367 |
+
current_url = url
|
| 368 |
+
current_method = method
|
| 369 |
+
current_body = body_bytes
|
| 370 |
+
redirects_followed = 0
|
| 371 |
+
previous_origin: tuple[str, str, int] | None = None
|
| 372 |
+
|
| 373 |
+
while True:
|
| 374 |
+
target, validation_error = _validate_target(
|
| 375 |
+
current_url,
|
| 376 |
+
allow_private=allow_private,
|
| 377 |
+
deadline=deadline,
|
| 378 |
+
)
|
| 379 |
+
if validation_error or target is None:
|
| 380 |
+
return None, validation_error or "INVALID_URL"
|
| 381 |
+
|
| 382 |
+
if previous_origin is not None and target.origin != previous_origin:
|
| 383 |
+
active_headers = {
|
| 384 |
+
key: value
|
| 385 |
+
for key, value in active_headers.items()
|
| 386 |
+
if key.lower() not in _SENSITIVE_REDIRECT_HEADERS
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
response, connection, request_error = _request_once(
|
| 390 |
+
target,
|
| 391 |
+
method=current_method,
|
| 392 |
+
body=current_body,
|
| 393 |
+
headers=active_headers,
|
| 394 |
+
deadline=deadline,
|
| 395 |
+
)
|
| 396 |
+
if request_error or response is None or connection is None:
|
| 397 |
+
return None, request_error or "NETWORK_FAILURE"
|
| 398 |
+
try:
|
| 399 |
+
status = int(response.status)
|
| 400 |
+
if status in _REDIRECT_STATUSES:
|
| 401 |
+
location = response.getheader("Location")
|
| 402 |
+
if not location:
|
| 403 |
+
return None, "REDIRECT_MISSING_LOCATION"
|
| 404 |
+
if len(location.encode("utf-8", "ignore")) > MAX_LOCATION_BYTES:
|
| 405 |
+
return None, "REDIRECT_LOCATION_TOO_LARGE"
|
| 406 |
+
if redirects_followed >= max_redirects:
|
| 407 |
+
return None, "REDIRECT_LIMIT_EXCEEDED"
|
| 408 |
+
next_url = urljoin(current_url, location)
|
| 409 |
+
if status == 303:
|
| 410 |
+
current_method = "GET"
|
| 411 |
+
current_body = None
|
| 412 |
+
active_headers = {
|
| 413 |
+
key: value
|
| 414 |
+
for key, value in active_headers.items()
|
| 415 |
+
if key.lower() != "content-type"
|
| 416 |
+
}
|
| 417 |
+
previous_origin = target.origin
|
| 418 |
+
current_url = next_url
|
| 419 |
+
redirects_followed += 1
|
| 420 |
+
continue
|
| 421 |
+
|
| 422 |
+
if not 200 <= status < 300:
|
| 423 |
+
return None, f"HTTP_STATUS:{status}"
|
| 424 |
+
|
| 425 |
+
content_length = response.getheader("Content-Length")
|
| 426 |
+
if content_length:
|
| 427 |
+
try:
|
| 428 |
+
parsed_length = int(content_length)
|
| 429 |
+
if parsed_length < 0:
|
| 430 |
+
return None, "INVALID_CONTENT_LENGTH"
|
| 431 |
+
if parsed_length > max_response_bytes:
|
| 432 |
+
return None, "RESPONSE_TOO_LARGE"
|
| 433 |
+
except ValueError:
|
| 434 |
+
return None, "INVALID_CONTENT_LENGTH"
|
| 435 |
+
read_budget = _remaining(deadline)
|
| 436 |
+
if read_budget <= 0:
|
| 437 |
+
return None, "TIMEOUT"
|
| 438 |
+
if connection.sock is not None:
|
| 439 |
+
connection.sock.settimeout(read_budget)
|
| 440 |
+
raw = response.read(max_response_bytes + 1)
|
| 441 |
+
if len(raw) > max_response_bytes:
|
| 442 |
+
return None, "RESPONSE_TOO_LARGE"
|
| 443 |
+
try:
|
| 444 |
+
return json.loads(raw.decode("utf-8")), None
|
| 445 |
+
except (UnicodeDecodeError, json.JSONDecodeError):
|
| 446 |
+
return None, "INVALID_JSON"
|
| 447 |
+
except (TimeoutError, socket.timeout):
|
| 448 |
+
return None, "TIMEOUT"
|
| 449 |
+
except Exception:
|
| 450 |
+
return None, "NETWORK_FAILURE"
|
| 451 |
+
finally:
|
| 452 |
+
connection.close()
|
| 453 |
+
|
| 454 |
+
|
| 455 |
+
__all__ = [
|
| 456 |
+
"DEFAULT_MAX_REDIRECTS",
|
| 457 |
+
"DEFAULT_MAX_RESPONSE_BYTES",
|
| 458 |
+
"DEFAULT_TIMEOUT_S",
|
| 459 |
+
"MAX_REDIRECTS",
|
| 460 |
+
"MAX_RESPONSE_BYTES",
|
| 461 |
+
"MAX_TIMEOUT_S",
|
| 462 |
+
"http_json",
|
| 463 |
+
]
|
|
@@ -103,10 +103,19 @@ def _qbio_status() -> Dict[str, Any]:
|
|
| 103 |
comp = qb.compass(50.0)
|
| 104 |
lam = qb.lambda_v5(0.9, 121.5, 130.0)
|
| 105 |
sources = dict(getattr(qb, "SOURCES", {}))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
models = [
|
| 107 |
{"model": "Mitchell proton-motive force",
|
| 108 |
"equation": "Δp = ΔΨ − (2.3 RT / F)·ΔpH (mV)",
|
| 109 |
"value_mV": pmf_single, "status": "VERIFIED",
|
|
|
|
| 110 |
"source": sources.get("Mitchell pmf (Nobel)"),
|
| 111 |
"endpoint": f"{base}/pmf"},
|
| 112 |
{"model": "Two-ion K+/H+ pmf correction",
|
|
@@ -115,10 +124,12 @@ def _qbio_status() -> Dict[str, Any]:
|
|
| 115 |
{"model": "Lindblad / GKSL coherence decay",
|
| 116 |
"equation": "dρ/dt = −(i/ħ)[H,ρ] + Σ γ_k (L_k ρ L_k† − ½{L_k†L_k, ρ})",
|
| 117 |
"fitted_tau_c": coh.get("tau_c"), "status": "VERIFIED",
|
|
|
|
| 118 |
"endpoint": f"{base}/coherence"},
|
| 119 |
{"model": "Radical-pair magnetoreception (singlet yield)",
|
| 120 |
"angular_contrast": comp.get("angular_contrast"),
|
| 121 |
"compass_works": comp.get("works"), "status": "VERIFIED",
|
|
|
|
| 122 |
"fidelity": "reduced single-nucleus closed-form (full model contrast ~0.378)",
|
| 123 |
"endpoint": f"{base}/compass"},
|
| 124 |
{"model": "SZL Λ-v5 closure gate",
|
|
@@ -150,8 +161,12 @@ def _qbio_status() -> Dict[str, Any]:
|
|
| 150 |
"live_paths": live_paths,
|
| 151 |
"summary_endpoint": summary_src,
|
| 152 |
"models": models,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
"status_legend": {
|
| 154 |
-
"VERIFIED": "executed model, reproduces on every call",
|
| 155 |
"PROPOSED": "SZL-proposed construct (two-ion pmf, Λ-v5 gate)",
|
| 156 |
"NARRATIVE": "Jack Kruse framing only — NOT load-bearing math",
|
| 157 |
},
|
|
|
|
| 103 |
comp = qb.compass(50.0)
|
| 104 |
lam = qb.lambda_v5(0.9, 121.5, 130.0)
|
| 105 |
sources = dict(getattr(qb, "SOURCES", {}))
|
| 106 |
+
verification_scope = getattr(
|
| 107 |
+
qb, "VERIFICATION_SCOPE", "COMPUTATIONAL_REPRODUCIBILITY_ONLY"
|
| 108 |
+
)
|
| 109 |
+
verification_boundary = getattr(
|
| 110 |
+
qb,
|
| 111 |
+
"VERIFICATION_BOUNDARY",
|
| 112 |
+
"Executed deterministic model output; not experimental validation.",
|
| 113 |
+
)
|
| 114 |
models = [
|
| 115 |
{"model": "Mitchell proton-motive force",
|
| 116 |
"equation": "Δp = ΔΨ − (2.3 RT / F)·ΔpH (mV)",
|
| 117 |
"value_mV": pmf_single, "status": "VERIFIED",
|
| 118 |
+
"verification_scope": verification_scope,
|
| 119 |
"source": sources.get("Mitchell pmf (Nobel)"),
|
| 120 |
"endpoint": f"{base}/pmf"},
|
| 121 |
{"model": "Two-ion K+/H+ pmf correction",
|
|
|
|
| 124 |
{"model": "Lindblad / GKSL coherence decay",
|
| 125 |
"equation": "dρ/dt = −(i/ħ)[H,ρ] + Σ γ_k (L_k ρ L_k† − ½{L_k†L_k, ρ})",
|
| 126 |
"fitted_tau_c": coh.get("tau_c"), "status": "VERIFIED",
|
| 127 |
+
"verification_scope": verification_scope,
|
| 128 |
"endpoint": f"{base}/coherence"},
|
| 129 |
{"model": "Radical-pair magnetoreception (singlet yield)",
|
| 130 |
"angular_contrast": comp.get("angular_contrast"),
|
| 131 |
"compass_works": comp.get("works"), "status": "VERIFIED",
|
| 132 |
+
"verification_scope": verification_scope,
|
| 133 |
"fidelity": "reduced single-nucleus closed-form (full model contrast ~0.378)",
|
| 134 |
"endpoint": f"{base}/compass"},
|
| 135 |
{"model": "SZL Λ-v5 closure gate",
|
|
|
|
| 161 |
"live_paths": live_paths,
|
| 162 |
"summary_endpoint": summary_src,
|
| 163 |
"models": models,
|
| 164 |
+
"verification_scope": verification_scope if models else "UNAVAILABLE",
|
| 165 |
+
"verification_boundary": verification_boundary if models else (
|
| 166 |
+
"Backing model unavailable; no verification claim emitted."
|
| 167 |
+
),
|
| 168 |
"status_legend": {
|
| 169 |
+
"VERIFIED": "executed deterministic model, reproduces on every call; not experimental validation",
|
| 170 |
"PROPOSED": "SZL-proposed construct (two-ion pmf, Λ-v5 gate)",
|
| 171 |
"NARRATIVE": "Jack Kruse framing only — NOT load-bearing math",
|
| 172 |
},
|
|
@@ -55,6 +55,17 @@ SOURCES = {
|
|
| 55 |
"AdS/CFT (Maldacena)": "https://en.wikipedia.org/wiki/Holographic_principle",
|
| 56 |
}
|
| 57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
def _now():
|
| 60 |
return datetime.now(timezone.utc).isoformat()
|
|
@@ -160,6 +171,8 @@ def _h_pmf(req: Request):
|
|
| 160 |
"model": "Mitchell proton-motive force",
|
| 161 |
"equation": "Δp = ΔΨ − (2.3 RT / F)·ΔpH (mV)",
|
| 162 |
"status": "VERIFIED",
|
|
|
|
|
|
|
| 163 |
"two_ion_status": "PROPOSED",
|
| 164 |
"inputs": {"d_psi_mV": d_psi, "d_pH": d_pH, "d_pK": d_pK, "K_weight": w},
|
| 165 |
"pmf_single_ion_mV": single,
|
|
@@ -174,7 +187,9 @@ def _h_coherence(req: Request):
|
|
| 174 |
return JSONResponse({
|
| 175 |
"model": "Lindblad / GKSL open-quantum-system coherence",
|
| 176 |
"equation": "dρ/dt = −(i/ħ)[H,ρ] + Σ γ_k (L_k ρ L_k† − ½{L_k†L_k, ρ})",
|
| 177 |
-
"status": "VERIFIED", "
|
|
|
|
|
|
|
| 178 |
"source": SOURCES["Lindblad path integral"], "computed_at": _now(),
|
| 179 |
})
|
| 180 |
|
|
@@ -188,6 +203,8 @@ def _h_compass(req: Request):
|
|
| 188 |
angles = (0.0, 30.0, 60.0, 90.0)
|
| 189 |
out = compass(B, angles)
|
| 190 |
out.update({"model": "Radical-pair magnetoreception (singlet yield)", "status": "VERIFIED",
|
|
|
|
|
|
|
| 191 |
"honest_note": "Reduced single-nucleus closed-form here gives a real angle-dependent yield (contrast ~0.025); the FULL multi-spin density-matrix model in the payload yields contrast ~0.378. A toy isotropic cos(ωt) model fails (contrast~0). Anisotropy is genuine, not fabricated.",
|
| 192 |
"fidelity": "reduced (single-nucleus closed-form)",
|
| 193 |
"source": SOURCES["Hore PNAS 2009"], "computed_at": _now()})
|
|
@@ -207,14 +224,19 @@ def _h_lambda(req: Request):
|
|
| 207 |
def _h_summary(req: Request):
|
| 208 |
return JSONResponse({
|
| 209 |
"title": "SZL Quantum-Bio Master Payload (v5) — verified results",
|
| 210 |
-
"
|
|
|
|
|
|
|
| 211 |
"PROPOSED": "SZL-proposed construct",
|
| 212 |
"NARRATIVE": "Jack Kruse framing only — NOT load-bearing math"},
|
| 213 |
"results": [
|
| 214 |
-
{"quantity": "Lindblad τ_c", "value": 6.05, "status": "VERIFIED"
|
| 215 |
-
|
|
|
|
|
|
|
| 216 |
{"quantity": "pmf two-ion K+/H+ (mV)", "value": round(pmf_two_ion(150.0, 0.5, 0.30), 1), "status": "PROPOSED"},
|
| 217 |
-
{"quantity": "compass angular contrast", "value": compass(50.0)["angular_contrast"], "status": "VERIFIED"
|
|
|
|
| 218 |
{"quantity": "Λ-v5 gate", "value": "coherent AND charged -> execute; else recharge", "status": "PROPOSED"},
|
| 219 |
{"quantity": "Lean closure theorems", "value": 3, "status": "VERIFIED (proofs, no sorry)"},
|
| 220 |
],
|
|
|
|
| 55 |
"AdS/CFT (Maldacena)": "https://en.wikipedia.org/wiki/Holographic_principle",
|
| 56 |
}
|
| 57 |
|
| 58 |
+
# ``VERIFIED`` is retained for backward compatibility with existing clients, but its
|
| 59 |
+
# scope is deliberately narrow: the implementation executes deterministically and
|
| 60 |
+
# reproduces the reported model output. It is not an experimental validation of a
|
| 61 |
+
# biological mechanism, a physical device measurement, or evidence of quantum
|
| 62 |
+
# advantage.
|
| 63 |
+
VERIFICATION_SCOPE = "COMPUTATIONAL_REPRODUCIBILITY_ONLY"
|
| 64 |
+
VERIFICATION_BOUNDARY = (
|
| 65 |
+
"Executed deterministic model output; not experimental validation, not an "
|
| 66 |
+
"instrument measurement, and not evidence of quantum advantage."
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
|
| 70 |
def _now():
|
| 71 |
return datetime.now(timezone.utc).isoformat()
|
|
|
|
| 171 |
"model": "Mitchell proton-motive force",
|
| 172 |
"equation": "Δp = ΔΨ − (2.3 RT / F)·ΔpH (mV)",
|
| 173 |
"status": "VERIFIED",
|
| 174 |
+
"verification_scope": VERIFICATION_SCOPE,
|
| 175 |
+
"verification_boundary": VERIFICATION_BOUNDARY,
|
| 176 |
"two_ion_status": "PROPOSED",
|
| 177 |
"inputs": {"d_psi_mV": d_psi, "d_pH": d_pH, "d_pK": d_pK, "K_weight": w},
|
| 178 |
"pmf_single_ion_mV": single,
|
|
|
|
| 187 |
return JSONResponse({
|
| 188 |
"model": "Lindblad / GKSL open-quantum-system coherence",
|
| 189 |
"equation": "dρ/dt = −(i/ħ)[H,ρ] + Σ γ_k (L_k ρ L_k† − ½{L_k†L_k, ρ})",
|
| 190 |
+
"status": "VERIFIED", "verification_scope": VERIFICATION_SCOPE,
|
| 191 |
+
"verification_boundary": VERIFICATION_BOUNDARY,
|
| 192 |
+
"fitted_tau_c": s["tau_c"], "series": s,
|
| 193 |
"source": SOURCES["Lindblad path integral"], "computed_at": _now(),
|
| 194 |
})
|
| 195 |
|
|
|
|
| 203 |
angles = (0.0, 30.0, 60.0, 90.0)
|
| 204 |
out = compass(B, angles)
|
| 205 |
out.update({"model": "Radical-pair magnetoreception (singlet yield)", "status": "VERIFIED",
|
| 206 |
+
"verification_scope": VERIFICATION_SCOPE,
|
| 207 |
+
"verification_boundary": VERIFICATION_BOUNDARY,
|
| 208 |
"honest_note": "Reduced single-nucleus closed-form here gives a real angle-dependent yield (contrast ~0.025); the FULL multi-spin density-matrix model in the payload yields contrast ~0.378. A toy isotropic cos(ωt) model fails (contrast~0). Anisotropy is genuine, not fabricated.",
|
| 209 |
"fidelity": "reduced (single-nucleus closed-form)",
|
| 210 |
"source": SOURCES["Hore PNAS 2009"], "computed_at": _now()})
|
|
|
|
| 224 |
def _h_summary(req: Request):
|
| 225 |
return JSONResponse({
|
| 226 |
"title": "SZL Quantum-Bio Master Payload (v5) — verified results",
|
| 227 |
+
"verification_scope": VERIFICATION_SCOPE,
|
| 228 |
+
"verification_boundary": VERIFICATION_BOUNDARY,
|
| 229 |
+
"status_legend": {"VERIFIED": "executed deterministic model, reproduces on call; not experimental validation",
|
| 230 |
"PROPOSED": "SZL-proposed construct",
|
| 231 |
"NARRATIVE": "Jack Kruse framing only — NOT load-bearing math"},
|
| 232 |
"results": [
|
| 233 |
+
{"quantity": "Lindblad τ_c", "value": 6.05, "status": "VERIFIED",
|
| 234 |
+
"verification_scope": VERIFICATION_SCOPE},
|
| 235 |
+
{"quantity": "pmf single-ion (mV)", "value": round(pmf(150.0, 0.5), 1), "status": "VERIFIED",
|
| 236 |
+
"verification_scope": VERIFICATION_SCOPE},
|
| 237 |
{"quantity": "pmf two-ion K+/H+ (mV)", "value": round(pmf_two_ion(150.0, 0.5, 0.30), 1), "status": "PROPOSED"},
|
| 238 |
+
{"quantity": "compass angular contrast", "value": compass(50.0)["angular_contrast"], "status": "VERIFIED",
|
| 239 |
+
"verification_scope": VERIFICATION_SCOPE},
|
| 240 |
{"quantity": "Λ-v5 gate", "value": "coherent AND charged -> execute; else recharge", "status": "PROPOSED"},
|
| 241 |
{"quantity": "Lean closure theorems", "value": 3, "status": "VERIFIED (proofs, no sorry)"},
|
| 242 |
],
|
|
@@ -0,0 +1,724 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Bounded, proof-carrying quantum workflow utility proposals.
|
| 3 |
+
|
| 4 |
+
This clean-room module is deliberately smaller than a quantum SDK. It accepts
|
| 5 |
+
typed QUBO and Hamiltonian descriptions, produces deterministic *proposals*,
|
| 6 |
+
and makes unsupported advantage language fail closed. It performs no network,
|
| 7 |
+
filesystem, subprocess, provider, simulator, QPU, credential, or deployment
|
| 8 |
+
operation. ``effectors`` and ``provider_calls`` are always zero.
|
| 9 |
+
|
| 10 |
+
The finance ``szl_gpu_quant`` engine is a separate system and is not imported.
|
| 11 |
+
The repository's ``szl_vqc`` state-vector demonstration remains a small
|
| 12 |
+
``MODELED`` / ``SIMULATED`` capability; it is described by the manifest but is
|
| 13 |
+
not treated as hardware evidence or an advantage baseline.
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
from __future__ import annotations
|
| 17 |
+
|
| 18 |
+
import hashlib
|
| 19 |
+
import json
|
| 20 |
+
import math
|
| 21 |
+
import re
|
| 22 |
+
import time
|
| 23 |
+
from dataclasses import asdict, dataclass
|
| 24 |
+
from enum import Enum
|
| 25 |
+
from typing import Any, Mapping, Sequence
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
SCHEMA_VERSION = "szl.quantum-utility.v1"
|
| 29 |
+
RECEIPT_SCHEMA_VERSION = "szl.quantum-utility.receipt.v1"
|
| 30 |
+
MODE = "PROPOSAL_ONLY"
|
| 31 |
+
EFFECTORS = 0
|
| 32 |
+
PROVIDER_CALLS = 0
|
| 33 |
+
MAX_QUBO_VARIABLES = 16
|
| 34 |
+
MAX_EXACT_STATES = 1 << MAX_QUBO_VARIABLES
|
| 35 |
+
MAX_EXACT_RUNTIME_MS = 2_000
|
| 36 |
+
MAX_HAMILTONIAN_QUBITS = 128
|
| 37 |
+
MAX_HAMILTONIAN_TERMS = 2_048
|
| 38 |
+
MIN_SHOTS = 1
|
| 39 |
+
MAX_SHOTS = 1_000_000
|
| 40 |
+
MIN_REPEATED_MEASUREMENTS = 3
|
| 41 |
+
_SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class ContractError(ValueError):
|
| 45 |
+
"""Raised when an input cannot be represented by the bounded contract."""
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class EvidenceLabel(str, Enum):
|
| 49 |
+
DECLARED = "DECLARED"
|
| 50 |
+
MEASURED = "MEASURED"
|
| 51 |
+
UNKNOWN = "UNKNOWN"
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
@dataclass(frozen=True)
|
| 55 |
+
class QUBOTerm:
|
| 56 |
+
left: str
|
| 57 |
+
right: str
|
| 58 |
+
coefficient: float
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
@dataclass(frozen=True)
|
| 62 |
+
class QUBOProblem:
|
| 63 |
+
problem_id: str
|
| 64 |
+
variables: tuple[str, ...]
|
| 65 |
+
offset: float
|
| 66 |
+
linear: tuple[tuple[str, float], ...]
|
| 67 |
+
quadratic: tuple[QUBOTerm, ...]
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
@dataclass(frozen=True)
|
| 71 |
+
class HamiltonianTerm:
|
| 72 |
+
term_id: str
|
| 73 |
+
pauli: str
|
| 74 |
+
coefficient: float
|
| 75 |
+
declared_priority: float
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
@dataclass(frozen=True)
|
| 79 |
+
class HamiltonianProblem:
|
| 80 |
+
problem_id: str
|
| 81 |
+
qubit_count: int
|
| 82 |
+
terms: tuple[HamiltonianTerm, ...]
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
UTILITY_FIELDS = (
|
| 86 |
+
"bounded_value_usd",
|
| 87 |
+
"compute_cost_usd",
|
| 88 |
+
"queue_cost_usd",
|
| 89 |
+
"energy_cost_usd",
|
| 90 |
+
"verification_cost_usd",
|
| 91 |
+
"operational_risk_cost_usd",
|
| 92 |
+
"estimated_accuracy",
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def canonical_json(value: Any) -> bytes:
|
| 97 |
+
return json.dumps(
|
| 98 |
+
value,
|
| 99 |
+
sort_keys=True,
|
| 100 |
+
separators=(",", ":"),
|
| 101 |
+
ensure_ascii=False,
|
| 102 |
+
allow_nan=False,
|
| 103 |
+
).encode("utf-8")
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
def sha256_json(value: Any) -> str:
|
| 107 |
+
return hashlib.sha256(canonical_json(value)).hexdigest()
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def _mapping(value: Any, name: str) -> Mapping[str, Any]:
|
| 111 |
+
if not isinstance(value, Mapping):
|
| 112 |
+
raise ContractError(f"{name} must be an object")
|
| 113 |
+
return value
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def _text(value: Any, name: str) -> str:
|
| 117 |
+
if not isinstance(value, str) or not value.strip():
|
| 118 |
+
raise ContractError(f"{name} must be a non-empty string")
|
| 119 |
+
return value.strip()
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def _number(value: Any, name: str) -> float:
|
| 123 |
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
| 124 |
+
raise ContractError(f"{name} must be a finite number")
|
| 125 |
+
out = float(value)
|
| 126 |
+
if not math.isfinite(out):
|
| 127 |
+
raise ContractError(f"{name} must be a finite number")
|
| 128 |
+
return out
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def _integer(value: Any, name: str, minimum: int, maximum: int) -> int:
|
| 132 |
+
if isinstance(value, bool) or not isinstance(value, int):
|
| 133 |
+
raise ContractError(f"{name} must be an integer")
|
| 134 |
+
if not minimum <= value <= maximum:
|
| 135 |
+
raise ContractError(f"{name} must be between {minimum} and {maximum}")
|
| 136 |
+
return value
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def _digest(value: Any, name: str) -> str:
|
| 140 |
+
text = _text(value, name).lower()
|
| 141 |
+
if not _SHA256_RE.fullmatch(text):
|
| 142 |
+
raise ContractError(f"{name} must be a lowercase SHA-256 digest")
|
| 143 |
+
return text
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
def _strict_keys(value: Mapping[str, Any], allowed: set[str], name: str) -> None:
|
| 147 |
+
extras = sorted(set(value) - allowed)
|
| 148 |
+
if extras:
|
| 149 |
+
raise ContractError(f"{name} has unsupported fields: {', '.join(extras)}")
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def parse_qubo(payload: Mapping[str, Any]) -> QUBOProblem:
|
| 153 |
+
obj = _mapping(payload, "QUBO")
|
| 154 |
+
_strict_keys(obj, {"kind", "problem_id", "variables", "offset", "linear", "quadratic"}, "QUBO")
|
| 155 |
+
if obj.get("kind") != "QUBO":
|
| 156 |
+
raise ContractError("kind must be QUBO")
|
| 157 |
+
raw_variables = obj.get("variables")
|
| 158 |
+
if not isinstance(raw_variables, Sequence) or isinstance(raw_variables, (str, bytes)):
|
| 159 |
+
raise ContractError("variables must be an array")
|
| 160 |
+
variables = tuple(_text(v, "variable") for v in raw_variables)
|
| 161 |
+
if not variables or len(variables) > MAX_QUBO_VARIABLES:
|
| 162 |
+
raise ContractError(f"QUBO must contain 1..{MAX_QUBO_VARIABLES} variables")
|
| 163 |
+
if len(set(variables)) != len(variables):
|
| 164 |
+
raise ContractError("variables must be unique")
|
| 165 |
+
allowed_variables = set(variables)
|
| 166 |
+
|
| 167 |
+
raw_linear = obj.get("linear", {})
|
| 168 |
+
if not isinstance(raw_linear, Mapping):
|
| 169 |
+
raise ContractError("linear must be an object")
|
| 170 |
+
unknown_linear = sorted(set(raw_linear) - allowed_variables)
|
| 171 |
+
if unknown_linear:
|
| 172 |
+
raise ContractError(f"linear references unknown variables: {', '.join(unknown_linear)}")
|
| 173 |
+
linear = tuple(sorted((str(k), _number(v, f"linear.{k}")) for k, v in raw_linear.items()))
|
| 174 |
+
|
| 175 |
+
raw_quadratic = obj.get("quadratic", [])
|
| 176 |
+
if not isinstance(raw_quadratic, Sequence) or isinstance(raw_quadratic, (str, bytes)):
|
| 177 |
+
raise ContractError("quadratic must be an array")
|
| 178 |
+
terms: list[QUBOTerm] = []
|
| 179 |
+
seen: set[tuple[str, str]] = set()
|
| 180 |
+
for index, raw in enumerate(raw_quadratic):
|
| 181 |
+
term = _mapping(raw, f"quadratic[{index}]")
|
| 182 |
+
_strict_keys(term, {"left", "right", "coefficient"}, f"quadratic[{index}]")
|
| 183 |
+
left = _text(term.get("left"), f"quadratic[{index}].left")
|
| 184 |
+
right = _text(term.get("right"), f"quadratic[{index}].right")
|
| 185 |
+
if left not in allowed_variables or right not in allowed_variables:
|
| 186 |
+
raise ContractError(f"quadratic[{index}] references an unknown variable")
|
| 187 |
+
if left == right:
|
| 188 |
+
raise ContractError("diagonal QUBO terms belong in linear")
|
| 189 |
+
pair = tuple(sorted((left, right)))
|
| 190 |
+
if pair in seen:
|
| 191 |
+
raise ContractError(f"duplicate quadratic pair: {pair[0]},{pair[1]}")
|
| 192 |
+
seen.add(pair)
|
| 193 |
+
terms.append(QUBOTerm(pair[0], pair[1], _number(term.get("coefficient"), "coefficient")))
|
| 194 |
+
terms.sort(key=lambda row: (row.left, row.right))
|
| 195 |
+
return QUBOProblem(
|
| 196 |
+
problem_id=_text(obj.get("problem_id"), "problem_id"),
|
| 197 |
+
variables=variables,
|
| 198 |
+
offset=_number(obj.get("offset", 0.0), "offset"),
|
| 199 |
+
linear=linear,
|
| 200 |
+
quadratic=tuple(terms),
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def solve_qubo_exact(payload: Mapping[str, Any]) -> dict[str, Any]:
|
| 205 |
+
"""Enumerate a small binary QUBO exactly, with hard state/time ceilings."""
|
| 206 |
+
|
| 207 |
+
problem = parse_qubo(payload)
|
| 208 |
+
max_runtime_ms = MAX_EXACT_RUNTIME_MS
|
| 209 |
+
deadline = time.perf_counter() + max_runtime_ms / 1_000.0
|
| 210 |
+
linear = dict(problem.linear)
|
| 211 |
+
best_energy: float | None = None
|
| 212 |
+
best_bits: tuple[int, ...] | None = None
|
| 213 |
+
state_count = 1 << len(problem.variables)
|
| 214 |
+
if state_count > MAX_EXACT_STATES:
|
| 215 |
+
raise ContractError("exact QUBO state ceiling exceeded")
|
| 216 |
+
|
| 217 |
+
for state in range(state_count):
|
| 218 |
+
if state % 1_024 == 0 and time.perf_counter() > deadline:
|
| 219 |
+
raise ContractError("exact QUBO time limit exceeded; no partial baseline emitted")
|
| 220 |
+
bits = tuple((state >> index) & 1 for index in range(len(problem.variables)))
|
| 221 |
+
assignment = dict(zip(problem.variables, bits))
|
| 222 |
+
energy = problem.offset
|
| 223 |
+
energy += sum(linear.get(name, 0.0) * assignment[name] for name in problem.variables)
|
| 224 |
+
energy += sum(term.coefficient * assignment[term.left] * assignment[term.right] for term in problem.quadratic)
|
| 225 |
+
if best_energy is None or energy < best_energy or (energy == best_energy and bits < best_bits):
|
| 226 |
+
best_energy = energy
|
| 227 |
+
best_bits = bits
|
| 228 |
+
|
| 229 |
+
assert best_energy is not None and best_bits is not None
|
| 230 |
+
return {
|
| 231 |
+
"problem_id": problem.problem_id,
|
| 232 |
+
"problem_digest": sha256_json(asdict(problem)),
|
| 233 |
+
"solver": "EXACT_BINARY_ENUMERATION",
|
| 234 |
+
"evidence_label": EvidenceLabel.MEASURED.value,
|
| 235 |
+
"measurement_scope": "deterministic classical computation",
|
| 236 |
+
"complete": True,
|
| 237 |
+
"variable_count": len(problem.variables),
|
| 238 |
+
"states_evaluated": state_count,
|
| 239 |
+
"objective": best_energy,
|
| 240 |
+
"assignment": dict(zip(problem.variables, best_bits)),
|
| 241 |
+
"max_runtime_ms": max_runtime_ms,
|
| 242 |
+
"quantum_hardware_used": False,
|
| 243 |
+
"quantum_advantage_claimed": False,
|
| 244 |
+
"mode": MODE,
|
| 245 |
+
"effectors": EFFECTORS,
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
def exact_baseline(request: Mapping[str, Any]) -> dict[str, Any]:
|
| 250 |
+
obj = _mapping(request, "exact baseline request")
|
| 251 |
+
_strict_keys(obj, {"problem", "max_runtime_ms"}, "exact baseline request")
|
| 252 |
+
problem_payload = dict(_mapping(obj.get("problem"), "problem"))
|
| 253 |
+
limit = _integer(obj.get("max_runtime_ms", MAX_EXACT_RUNTIME_MS), "max_runtime_ms", 1, MAX_EXACT_RUNTIME_MS)
|
| 254 |
+
problem = parse_qubo(problem_payload)
|
| 255 |
+
# Avoid widening the typed QUBO schema merely to carry an execution bound.
|
| 256 |
+
deadline = time.perf_counter() + limit / 1_000.0
|
| 257 |
+
linear = dict(problem.linear)
|
| 258 |
+
best: tuple[float, tuple[int, ...]] | None = None
|
| 259 |
+
state_count = 1 << len(problem.variables)
|
| 260 |
+
for state in range(state_count):
|
| 261 |
+
if state % 1_024 == 0 and time.perf_counter() > deadline:
|
| 262 |
+
raise ContractError("exact QUBO time limit exceeded; no partial baseline emitted")
|
| 263 |
+
bits = tuple((state >> index) & 1 for index in range(len(problem.variables)))
|
| 264 |
+
assignment = dict(zip(problem.variables, bits))
|
| 265 |
+
energy = problem.offset
|
| 266 |
+
energy += sum(linear.get(name, 0.0) * assignment[name] for name in problem.variables)
|
| 267 |
+
energy += sum(t.coefficient * assignment[t.left] * assignment[t.right] for t in problem.quadratic)
|
| 268 |
+
candidate = (energy, bits)
|
| 269 |
+
if best is None or candidate < best:
|
| 270 |
+
best = candidate
|
| 271 |
+
assert best is not None
|
| 272 |
+
return {
|
| 273 |
+
"problem_id": problem.problem_id,
|
| 274 |
+
"problem_digest": sha256_json(asdict(problem)),
|
| 275 |
+
"solver": "EXACT_BINARY_ENUMERATION",
|
| 276 |
+
"evidence_label": EvidenceLabel.MEASURED.value,
|
| 277 |
+
"measurement_scope": "deterministic classical computation",
|
| 278 |
+
"complete": True,
|
| 279 |
+
"variable_count": len(problem.variables),
|
| 280 |
+
"states_evaluated": state_count,
|
| 281 |
+
"objective": best[0],
|
| 282 |
+
"assignment": dict(zip(problem.variables, best[1])),
|
| 283 |
+
"max_runtime_ms": limit,
|
| 284 |
+
"quantum_hardware_used": False,
|
| 285 |
+
"quantum_advantage_claimed": False,
|
| 286 |
+
"mode": MODE,
|
| 287 |
+
"effectors": EFFECTORS,
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
def parse_hamiltonian(payload: Mapping[str, Any]) -> HamiltonianProblem:
|
| 292 |
+
obj = _mapping(payload, "Hamiltonian")
|
| 293 |
+
_strict_keys(obj, {"kind", "problem_id", "qubit_count", "terms"}, "Hamiltonian")
|
| 294 |
+
if obj.get("kind") != "HAMILTONIAN":
|
| 295 |
+
raise ContractError("kind must be HAMILTONIAN")
|
| 296 |
+
qubit_count = _integer(obj.get("qubit_count"), "qubit_count", 1, MAX_HAMILTONIAN_QUBITS)
|
| 297 |
+
raw_terms = obj.get("terms")
|
| 298 |
+
if not isinstance(raw_terms, Sequence) or isinstance(raw_terms, (str, bytes)):
|
| 299 |
+
raise ContractError("terms must be an array")
|
| 300 |
+
if not 1 <= len(raw_terms) <= MAX_HAMILTONIAN_TERMS:
|
| 301 |
+
raise ContractError(f"terms must contain 1..{MAX_HAMILTONIAN_TERMS} rows")
|
| 302 |
+
terms: list[HamiltonianTerm] = []
|
| 303 |
+
seen: set[str] = set()
|
| 304 |
+
for index, raw in enumerate(raw_terms):
|
| 305 |
+
row = _mapping(raw, f"terms[{index}]")
|
| 306 |
+
_strict_keys(row, {"term_id", "pauli", "coefficient", "declared_priority"}, f"terms[{index}]")
|
| 307 |
+
term_id = _text(row.get("term_id"), "term_id")
|
| 308 |
+
if term_id in seen:
|
| 309 |
+
raise ContractError(f"duplicate term_id: {term_id}")
|
| 310 |
+
seen.add(term_id)
|
| 311 |
+
pauli = _text(row.get("pauli"), "pauli").upper()
|
| 312 |
+
if len(pauli) != qubit_count or any(symbol not in "IXYZ" for symbol in pauli):
|
| 313 |
+
raise ContractError("pauli must contain exactly qubit_count symbols from I,X,Y,Z")
|
| 314 |
+
priority = _number(row.get("declared_priority", 1.0), "declared_priority")
|
| 315 |
+
if priority < 0:
|
| 316 |
+
raise ContractError("declared_priority must be non-negative")
|
| 317 |
+
terms.append(HamiltonianTerm(term_id, pauli, _number(row.get("coefficient"), "coefficient"), priority))
|
| 318 |
+
terms.sort(key=lambda row: row.term_id)
|
| 319 |
+
return HamiltonianProblem(_text(obj.get("problem_id"), "problem_id"), qubit_count, tuple(terms))
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
def allocate_hamiltonian_shots(request: Mapping[str, Any]) -> dict[str, Any]:
|
| 323 |
+
obj = _mapping(request, "Hamiltonian shot request")
|
| 324 |
+
_strict_keys(obj, {"hamiltonian", "shot_budget"}, "Hamiltonian shot request")
|
| 325 |
+
problem = parse_hamiltonian(_mapping(obj.get("hamiltonian"), "hamiltonian"))
|
| 326 |
+
budget = _integer(obj.get("shot_budget"), "shot_budget", MIN_SHOTS, MAX_SHOTS)
|
| 327 |
+
if budget < len(problem.terms):
|
| 328 |
+
raise ContractError("shot_budget must allocate at least one shot per term")
|
| 329 |
+
|
| 330 |
+
weights = []
|
| 331 |
+
for term in problem.terms:
|
| 332 |
+
locality = sum(symbol != "I" for symbol in term.pauli)
|
| 333 |
+
weights.append(abs(term.coefficient) * max(1, locality) * term.declared_priority)
|
| 334 |
+
total_weight = sum(weights)
|
| 335 |
+
if total_weight <= 0:
|
| 336 |
+
weights = [1.0] * len(problem.terms)
|
| 337 |
+
total_weight = float(len(weights))
|
| 338 |
+
|
| 339 |
+
remaining = budget - len(problem.terms)
|
| 340 |
+
exact_extra = [remaining * weight / total_weight for weight in weights]
|
| 341 |
+
floors = [int(math.floor(value)) for value in exact_extra]
|
| 342 |
+
leftover = remaining - sum(floors)
|
| 343 |
+
order = sorted(range(len(problem.terms)), key=lambda i: (-(exact_extra[i] - floors[i]), problem.terms[i].term_id))
|
| 344 |
+
extras = list(floors)
|
| 345 |
+
for index in order[:leftover]:
|
| 346 |
+
extras[index] += 1
|
| 347 |
+
|
| 348 |
+
allocations = []
|
| 349 |
+
for index, term in enumerate(problem.terms):
|
| 350 |
+
allocations.append({
|
| 351 |
+
"term_id": term.term_id,
|
| 352 |
+
"pauli": term.pauli,
|
| 353 |
+
"coefficient": term.coefficient,
|
| 354 |
+
"declared_priority": term.declared_priority,
|
| 355 |
+
"importance": weights[index],
|
| 356 |
+
"shots": 1 + extras[index],
|
| 357 |
+
})
|
| 358 |
+
return {
|
| 359 |
+
"problem_id": problem.problem_id,
|
| 360 |
+
"problem_digest": sha256_json(asdict(problem)),
|
| 361 |
+
"shot_budget": budget,
|
| 362 |
+
"shots_allocated": sum(row["shots"] for row in allocations),
|
| 363 |
+
"allocation": allocations,
|
| 364 |
+
"method": "DECLARED_ABS_COEFFICIENT_X_LOCALITY_X_PRIORITY_LARGEST_REMAINDER",
|
| 365 |
+
"method_evidence_label": EvidenceLabel.DECLARED.value,
|
| 366 |
+
"scientific_optimality_claimed": False,
|
| 367 |
+
"execution_performed": False,
|
| 368 |
+
"provider_calls": PROVIDER_CALLS,
|
| 369 |
+
"mode": MODE,
|
| 370 |
+
"effectors": EFFECTORS,
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
def _evidence_datum(value: Any, name: str, expected_unit: str) -> dict[str, Any]:
|
| 375 |
+
obj = _mapping(value, name)
|
| 376 |
+
_strict_keys(obj, {"value", "label", "unit", "source_ref"}, name)
|
| 377 |
+
try:
|
| 378 |
+
label = EvidenceLabel(_text(obj.get("label"), f"{name}.label"))
|
| 379 |
+
except ValueError as exc:
|
| 380 |
+
raise ContractError(f"{name}.label must be DECLARED, MEASURED, or UNKNOWN") from exc
|
| 381 |
+
unit = _text(obj.get("unit"), f"{name}.unit")
|
| 382 |
+
if unit != expected_unit:
|
| 383 |
+
raise ContractError(f"{name}.unit must be {expected_unit}")
|
| 384 |
+
source_ref = _text(obj.get("source_ref"), f"{name}.source_ref")
|
| 385 |
+
raw = obj.get("value")
|
| 386 |
+
if label is EvidenceLabel.UNKNOWN:
|
| 387 |
+
if raw is not None:
|
| 388 |
+
raise ContractError(f"{name}.value must be null when label is UNKNOWN")
|
| 389 |
+
numeric = None
|
| 390 |
+
else:
|
| 391 |
+
numeric = _number(raw, f"{name}.value")
|
| 392 |
+
if numeric < 0:
|
| 393 |
+
raise ContractError(f"{name}.value must be non-negative")
|
| 394 |
+
return {"value": numeric, "label": label.value, "unit": unit, "source_ref": source_ref}
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
def score_counterfactuals(request: Mapping[str, Any]) -> dict[str, Any]:
|
| 398 |
+
obj = _mapping(request, "counterfactual request")
|
| 399 |
+
_strict_keys(obj, {"workload_digest", "candidates"}, "counterfactual request")
|
| 400 |
+
workload_digest = _digest(obj.get("workload_digest"), "workload_digest")
|
| 401 |
+
raw_candidates = obj.get("candidates")
|
| 402 |
+
if not isinstance(raw_candidates, Sequence) or isinstance(raw_candidates, (str, bytes)):
|
| 403 |
+
raise ContractError("candidates must be an array")
|
| 404 |
+
if not 1 <= len(raw_candidates) <= 64:
|
| 405 |
+
raise ContractError("candidates must contain 1..64 rows")
|
| 406 |
+
seen: set[str] = set()
|
| 407 |
+
scored: list[dict[str, Any]] = []
|
| 408 |
+
expected_units = {name: ("ratio" if name == "estimated_accuracy" else "USD") for name in UTILITY_FIELDS}
|
| 409 |
+
for index, raw in enumerate(raw_candidates):
|
| 410 |
+
candidate = _mapping(raw, f"candidates[{index}]")
|
| 411 |
+
_strict_keys(candidate, {"candidate_id", "backend_id", "compile_plan_id", "inputs"}, f"candidates[{index}]")
|
| 412 |
+
candidate_id = _text(candidate.get("candidate_id"), "candidate_id")
|
| 413 |
+
if candidate_id in seen:
|
| 414 |
+
raise ContractError(f"duplicate candidate_id: {candidate_id}")
|
| 415 |
+
seen.add(candidate_id)
|
| 416 |
+
inputs = _mapping(candidate.get("inputs"), "inputs")
|
| 417 |
+
if set(inputs) != set(UTILITY_FIELDS):
|
| 418 |
+
raise ContractError("inputs must contain every utility field exactly once")
|
| 419 |
+
evidence = {name: _evidence_datum(inputs[name], name, expected_units[name]) for name in UTILITY_FIELDS}
|
| 420 |
+
accuracy = evidence["estimated_accuracy"]["value"]
|
| 421 |
+
if accuracy is not None and accuracy > 1:
|
| 422 |
+
raise ContractError("estimated_accuracy.value must be between 0 and 1")
|
| 423 |
+
labels = {row["label"] for row in evidence.values()}
|
| 424 |
+
unknown = sorted(name for name, row in evidence.items() if row["label"] == EvidenceLabel.UNKNOWN.value)
|
| 425 |
+
if unknown:
|
| 426 |
+
margin = None
|
| 427 |
+
score_label = EvidenceLabel.UNKNOWN.value
|
| 428 |
+
disposition = "UNKNOWN_INPUTS"
|
| 429 |
+
else:
|
| 430 |
+
margin = evidence["bounded_value_usd"]["value"] - sum(
|
| 431 |
+
evidence[name]["value"] for name in UTILITY_FIELDS
|
| 432 |
+
if name.endswith("_cost_usd") or name == "operational_risk_cost_usd"
|
| 433 |
+
)
|
| 434 |
+
score_label = EvidenceLabel.MEASURED.value if labels == {EvidenceLabel.MEASURED.value} else EvidenceLabel.DECLARED.value
|
| 435 |
+
disposition = "POSITIVE_MARGIN" if margin > 0 else "NON_POSITIVE_MARGIN"
|
| 436 |
+
scored.append({
|
| 437 |
+
"candidate_id": candidate_id,
|
| 438 |
+
"backend_id": _text(candidate.get("backend_id"), "backend_id"),
|
| 439 |
+
"compile_plan_id": _text(candidate.get("compile_plan_id"), "compile_plan_id"),
|
| 440 |
+
"inputs": evidence,
|
| 441 |
+
"unknown_inputs": unknown,
|
| 442 |
+
"utility_margin_usd": margin,
|
| 443 |
+
"score_evidence_label": score_label,
|
| 444 |
+
"disposition": disposition,
|
| 445 |
+
})
|
| 446 |
+
|
| 447 |
+
comparable = [row for row in scored if row["utility_margin_usd"] is not None]
|
| 448 |
+
front: list[str] = []
|
| 449 |
+
for row in comparable:
|
| 450 |
+
dominated = False
|
| 451 |
+
for other in comparable:
|
| 452 |
+
if other is row:
|
| 453 |
+
continue
|
| 454 |
+
row_accuracy = row["inputs"]["estimated_accuracy"]["value"]
|
| 455 |
+
other_accuracy = other["inputs"]["estimated_accuracy"]["value"]
|
| 456 |
+
if (
|
| 457 |
+
other["utility_margin_usd"] >= row["utility_margin_usd"]
|
| 458 |
+
and other_accuracy >= row_accuracy
|
| 459 |
+
and (other["utility_margin_usd"] > row["utility_margin_usd"] or other_accuracy > row_accuracy)
|
| 460 |
+
):
|
| 461 |
+
dominated = True
|
| 462 |
+
break
|
| 463 |
+
if not dominated:
|
| 464 |
+
front.append(row["candidate_id"])
|
| 465 |
+
return {
|
| 466 |
+
"workload_digest": workload_digest,
|
| 467 |
+
"candidates": sorted(scored, key=lambda row: row["candidate_id"]),
|
| 468 |
+
"pareto_front_candidate_ids": sorted(front),
|
| 469 |
+
"score_model": "DECLARED_VALUE_MINUS_TOTAL_DECLARED_OR_MEASURED_COST",
|
| 470 |
+
"universal_provider_ranking_claimed": False,
|
| 471 |
+
"execution_performed": False,
|
| 472 |
+
"provider_calls": PROVIDER_CALLS,
|
| 473 |
+
"mode": MODE,
|
| 474 |
+
"effectors": EFFECTORS,
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
def _receipt_body(operation: str, request: Mapping[str, Any], output: Mapping[str, Any]) -> dict[str, Any]:
|
| 479 |
+
return {
|
| 480 |
+
"schema_version": RECEIPT_SCHEMA_VERSION,
|
| 481 |
+
"operation": operation,
|
| 482 |
+
"mode": MODE,
|
| 483 |
+
"effectors": EFFECTORS,
|
| 484 |
+
"provider_calls": PROVIDER_CALLS,
|
| 485 |
+
"input": request,
|
| 486 |
+
"input_sha256": sha256_json(request),
|
| 487 |
+
"output": output,
|
| 488 |
+
"output_sha256": sha256_json(output),
|
| 489 |
+
"signature_state": "UNSIGNED_DETERMINISTIC_HASH_ONLY",
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
+
|
| 493 |
+
def create_receipt(operation: str, request: Mapping[str, Any], output: Mapping[str, Any]) -> dict[str, Any]:
|
| 494 |
+
body = _receipt_body(operation, request, output)
|
| 495 |
+
return {**body, "receipt_sha256": sha256_json(body)}
|
| 496 |
+
|
| 497 |
+
|
| 498 |
+
def evaluate_advantage_claim(request: Mapping[str, Any]) -> dict[str, Any]:
|
| 499 |
+
obj = _mapping(request, "advantage claim")
|
| 500 |
+
allowed = {
|
| 501 |
+
"claim_type", "claim_id", "claim_owner", "classical_baseline_receipt",
|
| 502 |
+
"quantum_observations", "uncertainty", "provenance", "utility_margin",
|
| 503 |
+
}
|
| 504 |
+
_strict_keys(obj, allowed, "advantage claim")
|
| 505 |
+
reasons: list[str] = []
|
| 506 |
+
if obj.get("claim_type") != "QUANTUM_ADVANTAGE":
|
| 507 |
+
reasons.append("QUG-001 claim_type must be QUANTUM_ADVANTAGE")
|
| 508 |
+
try:
|
| 509 |
+
_text(obj.get("claim_id"), "claim_id")
|
| 510 |
+
_text(obj.get("claim_owner"), "claim_owner")
|
| 511 |
+
except ContractError:
|
| 512 |
+
reasons.append("QUG-002 claim_id and accountable claim_owner are required")
|
| 513 |
+
|
| 514 |
+
baseline = obj.get("classical_baseline_receipt")
|
| 515 |
+
baseline_input_digest: str | None = None
|
| 516 |
+
try:
|
| 517 |
+
baseline_obj = _mapping(baseline, "classical_baseline_receipt")
|
| 518 |
+
if baseline_obj.get("operation") != "QUBO_EXACT_BASELINE":
|
| 519 |
+
raise ContractError("baseline receipt must be QUBO_EXACT_BASELINE")
|
| 520 |
+
baseline_check = replay_receipt(baseline_obj)
|
| 521 |
+
baseline_output = _mapping(baseline_obj.get("output"), "baseline output")
|
| 522 |
+
if (
|
| 523 |
+
not baseline_check["valid"]
|
| 524 |
+
or not baseline_output.get("complete")
|
| 525 |
+
or baseline_output.get("evidence_label") != EvidenceLabel.MEASURED.value
|
| 526 |
+
):
|
| 527 |
+
reasons.append("QUG-003 exact replayable classical baseline is required")
|
| 528 |
+
else:
|
| 529 |
+
baseline_input_digest = str(baseline_obj.get("input_sha256"))
|
| 530 |
+
except (ContractError, TypeError, KeyError):
|
| 531 |
+
reasons.append("QUG-003 exact replayable classical baseline is required")
|
| 532 |
+
|
| 533 |
+
observations = obj.get("quantum_observations")
|
| 534 |
+
observation_rows = observations if isinstance(observations, Sequence) and not isinstance(observations, (str, bytes)) else []
|
| 535 |
+
if len(observation_rows) < MIN_REPEATED_MEASUREMENTS:
|
| 536 |
+
reasons.append(f"QUG-004 at least {MIN_REPEATED_MEASUREMENTS} repeated measurements are required")
|
| 537 |
+
else:
|
| 538 |
+
run_ids: set[str] = set()
|
| 539 |
+
for index, raw in enumerate(observation_rows):
|
| 540 |
+
try:
|
| 541 |
+
row = _mapping(raw, f"quantum_observations[{index}]")
|
| 542 |
+
_strict_keys(row, {"run_id", "task_digest", "backend_id", "shots", "raw_result_sha256", "label"}, f"quantum_observations[{index}]")
|
| 543 |
+
run_id = _text(row.get("run_id"), "run_id")
|
| 544 |
+
if run_id in run_ids:
|
| 545 |
+
raise ContractError("run_id must be unique")
|
| 546 |
+
run_ids.add(run_id)
|
| 547 |
+
if row.get("label") != EvidenceLabel.MEASURED.value:
|
| 548 |
+
raise ContractError("observation label must be MEASURED")
|
| 549 |
+
if baseline_input_digest is None or _digest(row.get("task_digest"), "task_digest") != baseline_input_digest:
|
| 550 |
+
raise ContractError("task digest must match the classical baseline")
|
| 551 |
+
_text(row.get("backend_id"), "backend_id")
|
| 552 |
+
_integer(row.get("shots"), "shots", 1, MAX_SHOTS)
|
| 553 |
+
_digest(row.get("raw_result_sha256"), "raw_result_sha256")
|
| 554 |
+
except ContractError:
|
| 555 |
+
reasons.append(f"QUG-005 observation {index} is incomplete, incomparable, or not MEASURED")
|
| 556 |
+
break
|
| 557 |
+
|
| 558 |
+
margin_value: float | None = None
|
| 559 |
+
try:
|
| 560 |
+
margin = _evidence_datum(obj.get("utility_margin"), "utility_margin", "USD")
|
| 561 |
+
margin_value = margin["value"]
|
| 562 |
+
if margin["label"] != EvidenceLabel.MEASURED.value or margin_value is None or margin_value <= 0:
|
| 563 |
+
reasons.append("QUG-006 a positive MEASURED utility margin is required")
|
| 564 |
+
except ContractError:
|
| 565 |
+
reasons.append("QUG-006 a positive MEASURED utility margin is required")
|
| 566 |
+
|
| 567 |
+
try:
|
| 568 |
+
uncertainty = _mapping(obj.get("uncertainty"), "uncertainty")
|
| 569 |
+
_strict_keys(uncertainty, {"label", "method", "source_ref", "lower_margin_usd", "upper_margin_usd", "confidence"}, "uncertainty")
|
| 570 |
+
lower = _number(uncertainty.get("lower_margin_usd"), "lower_margin_usd")
|
| 571 |
+
upper = _number(uncertainty.get("upper_margin_usd"), "upper_margin_usd")
|
| 572 |
+
confidence = _number(uncertainty.get("confidence"), "confidence")
|
| 573 |
+
if (
|
| 574 |
+
uncertainty.get("label") != EvidenceLabel.MEASURED.value
|
| 575 |
+
or lower <= 0
|
| 576 |
+
or upper < lower
|
| 577 |
+
or not 0.5 <= confidence <= 1.0
|
| 578 |
+
or margin_value is None
|
| 579 |
+
or not lower <= margin_value <= upper
|
| 580 |
+
):
|
| 581 |
+
raise ContractError("uncertainty interval does not support a positive margin")
|
| 582 |
+
_text(uncertainty.get("method"), "uncertainty.method")
|
| 583 |
+
_text(uncertainty.get("source_ref"), "uncertainty.source_ref")
|
| 584 |
+
except ContractError:
|
| 585 |
+
reasons.append("QUG-007 measured uncertainty with a positive lower margin bound is required")
|
| 586 |
+
|
| 587 |
+
provenance = obj.get("provenance")
|
| 588 |
+
provenance_rows = provenance if isinstance(provenance, Sequence) and not isinstance(provenance, (str, bytes)) else []
|
| 589 |
+
if not provenance_rows:
|
| 590 |
+
reasons.append("QUG-008 provenance is required")
|
| 591 |
+
else:
|
| 592 |
+
try:
|
| 593 |
+
for index, raw in enumerate(provenance_rows):
|
| 594 |
+
row = _mapping(raw, f"provenance[{index}]")
|
| 595 |
+
_strict_keys(row, {"source_uri", "content_sha256", "observed_at"}, f"provenance[{index}]")
|
| 596 |
+
_text(row.get("source_uri"), "source_uri")
|
| 597 |
+
_digest(row.get("content_sha256"), "content_sha256")
|
| 598 |
+
_text(row.get("observed_at"), "observed_at")
|
| 599 |
+
except ContractError:
|
| 600 |
+
reasons.append("QUG-008 complete provenance is required")
|
| 601 |
+
|
| 602 |
+
unique_reasons = sorted(set(reasons))
|
| 603 |
+
if any(reason.startswith("QUG-006") for reason in unique_reasons) and margin_value is not None and margin_value <= 0:
|
| 604 |
+
evidence_state = "REFUTED"
|
| 605 |
+
elif unique_reasons:
|
| 606 |
+
evidence_state = "UNKNOWN"
|
| 607 |
+
else:
|
| 608 |
+
evidence_state = "SUPPORTED"
|
| 609 |
+
passed = not unique_reasons
|
| 610 |
+
return {
|
| 611 |
+
"claim_id": obj.get("claim_id"),
|
| 612 |
+
"claim_type": obj.get("claim_type"),
|
| 613 |
+
"gate_passed": passed,
|
| 614 |
+
"evidence_state": evidence_state,
|
| 615 |
+
"reasons": unique_reasons,
|
| 616 |
+
"eligible_for_human_review": passed,
|
| 617 |
+
"quantum_advantage_verified": False,
|
| 618 |
+
"claim_authorized": False,
|
| 619 |
+
"publication_authorized": False,
|
| 620 |
+
"execution_authorized": False,
|
| 621 |
+
"note": "Passing this gate means evidence completeness for human review, not verified quantum advantage.",
|
| 622 |
+
"mode": MODE,
|
| 623 |
+
"effectors": EFFECTORS,
|
| 624 |
+
"provider_calls": PROVIDER_CALLS,
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
+
|
| 628 |
+
OPERATIONS = {
|
| 629 |
+
"QUBO_EXACT_BASELINE": exact_baseline,
|
| 630 |
+
"HAMILTONIAN_SHOT_PLAN": allocate_hamiltonian_shots,
|
| 631 |
+
"COUNTERFACTUAL_SCORE": score_counterfactuals,
|
| 632 |
+
"QUANTUM_ADVANTAGE_GATE": evaluate_advantage_claim,
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
+
|
| 636 |
+
def run_with_receipt(operation: str, request: Mapping[str, Any]) -> dict[str, Any]:
|
| 637 |
+
if operation not in OPERATIONS:
|
| 638 |
+
raise ContractError(f"unsupported operation: {operation}")
|
| 639 |
+
normalized_request = dict(_mapping(request, "request"))
|
| 640 |
+
output = OPERATIONS[operation](normalized_request)
|
| 641 |
+
return {"result": output, "receipt": create_receipt(operation, normalized_request, output)}
|
| 642 |
+
|
| 643 |
+
|
| 644 |
+
def replay_receipt(receipt: Mapping[str, Any]) -> dict[str, Any]:
|
| 645 |
+
obj = _mapping(receipt, "receipt")
|
| 646 |
+
required = set(_receipt_body("x", {}, {})) | {"receipt_sha256"}
|
| 647 |
+
if set(obj) != required:
|
| 648 |
+
raise ContractError("receipt fields do not match the receipt schema")
|
| 649 |
+
if obj.get("schema_version") != RECEIPT_SCHEMA_VERSION:
|
| 650 |
+
raise ContractError("unsupported receipt schema_version")
|
| 651 |
+
if (
|
| 652 |
+
obj.get("mode") != MODE
|
| 653 |
+
or obj.get("effectors") != EFFECTORS
|
| 654 |
+
or obj.get("provider_calls") != PROVIDER_CALLS
|
| 655 |
+
or obj.get("signature_state") != "UNSIGNED_DETERMINISTIC_HASH_ONLY"
|
| 656 |
+
):
|
| 657 |
+
raise ContractError("receipt violates the proposal-only boundary")
|
| 658 |
+
operation = _text(obj.get("operation"), "operation")
|
| 659 |
+
request = dict(_mapping(obj.get("input"), "receipt.input"))
|
| 660 |
+
output = dict(_mapping(obj.get("output"), "receipt.output"))
|
| 661 |
+
stored = _digest(obj.get("receipt_sha256"), "receipt_sha256")
|
| 662 |
+
body = {key: obj[key] for key in obj if key != "receipt_sha256"}
|
| 663 |
+
hash_valid = sha256_json(body) == stored
|
| 664 |
+
input_valid = sha256_json(request) == obj.get("input_sha256")
|
| 665 |
+
output_valid = sha256_json(output) == obj.get("output_sha256")
|
| 666 |
+
if operation not in OPERATIONS:
|
| 667 |
+
replay_output: Mapping[str, Any] = {}
|
| 668 |
+
replay_equal = False
|
| 669 |
+
elif operation == "QUANTUM_ADVANTAGE_GATE":
|
| 670 |
+
# Advantage requests embed a baseline receipt. Replaying remains pure,
|
| 671 |
+
# bounded, and recursive only by one validated baseline level.
|
| 672 |
+
replay_output = OPERATIONS[operation](request)
|
| 673 |
+
replay_equal = replay_output == output
|
| 674 |
+
else:
|
| 675 |
+
replay_output = OPERATIONS[operation](request)
|
| 676 |
+
replay_equal = replay_output == output
|
| 677 |
+
valid = bool(hash_valid and input_valid and output_valid and replay_equal)
|
| 678 |
+
return {
|
| 679 |
+
"valid": valid,
|
| 680 |
+
"receipt_sha256": stored,
|
| 681 |
+
"hash_valid": hash_valid,
|
| 682 |
+
"input_digest_valid": input_valid,
|
| 683 |
+
"output_digest_valid": output_valid,
|
| 684 |
+
"replay_equal": replay_equal,
|
| 685 |
+
"mode": MODE,
|
| 686 |
+
"effectors": EFFECTORS,
|
| 687 |
+
"provider_calls": PROVIDER_CALLS,
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
|
| 691 |
+
def info() -> dict[str, Any]:
|
| 692 |
+
return {
|
| 693 |
+
"service": "szl-quantum-utility-gate",
|
| 694 |
+
"schema_version": SCHEMA_VERSION,
|
| 695 |
+
"ready": True,
|
| 696 |
+
"label": "STRUCTURAL-ONLY",
|
| 697 |
+
"label_detail": "Classical exact baselines may be MEASURED within their stated computation scope; no QPU measurement is made here.",
|
| 698 |
+
"mode": MODE,
|
| 699 |
+
"effectors": EFFECTORS,
|
| 700 |
+
"provider_calls": PROVIDER_CALLS,
|
| 701 |
+
"qpu_calls": 0,
|
| 702 |
+
"finance_quant_engine_imported": False,
|
| 703 |
+
"capabilities": {
|
| 704 |
+
"qubo_exact_classical_baseline": {"label": "MEASURED", "max_variables": MAX_QUBO_VARIABLES},
|
| 705 |
+
"hamiltonian_shot_allocation": {"label": "DECLARED", "max_terms": MAX_HAMILTONIAN_TERMS},
|
| 706 |
+
"counterfactual_backend_compile_scoring": {"labels_required": [label.value for label in EvidenceLabel]},
|
| 707 |
+
"quantum_advantage_rupture_gate": {"auto_verifies_advantage": False},
|
| 708 |
+
"deterministic_receipt_replay": True,
|
| 709 |
+
},
|
| 710 |
+
"existing_simulator_boundary": {
|
| 711 |
+
"module": "szl_vqc.py",
|
| 712 |
+
"label": "MODELED",
|
| 713 |
+
"sim_kind": "SIMULATED",
|
| 714 |
+
"used_as_hardware_evidence": False,
|
| 715 |
+
"used_as_advantage_evidence": False,
|
| 716 |
+
},
|
| 717 |
+
"non_goals": [
|
| 718 |
+
"QPU or provider execution",
|
| 719 |
+
"universal provider rankings",
|
| 720 |
+
"quantum advantage verification",
|
| 721 |
+
"finance portfolio analysis",
|
| 722 |
+
],
|
| 723 |
+
"operations": sorted(OPERATIONS),
|
| 724 |
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Canonical, machine-readable A11oy release identity.
|
| 2 |
+
|
| 3 |
+
The software-version DOI is intentionally absent until an immutable GitHub
|
| 4 |
+
release is archived and Zenodo returns a resolvable record. Existing research
|
| 5 |
+
DOIs remain separately typed so a UI cannot present either as the new release.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
import os
|
| 11 |
+
import re
|
| 12 |
+
import json
|
| 13 |
+
from pathlib import Path
|
| 14 |
+
from typing import Any
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
SOFTWARE_NAME = "A11oy"
|
| 18 |
+
SOFTWARE_VERSION = "1.1.0"
|
| 19 |
+
CANONICAL_URL = "https://a-11-oy.com"
|
| 20 |
+
LEGACY_ALIAS = "https://a11oy.net"
|
| 21 |
+
REPOSITORY_URL = "https://github.com/szl-holdings/a11oy"
|
| 22 |
+
CONCEPT_DOI = "10.5281/zenodo.19944926"
|
| 23 |
+
FORMAL_ARTIFACT_DOI = "10.5281/zenodo.20434276"
|
| 24 |
+
|
| 25 |
+
_ZENODO_DOI_RE = re.compile(r"^10\.5281/zenodo\.\d+$")
|
| 26 |
+
_EXPECTED_RELEASE_TAG = f"v{SOFTWARE_VERSION}"
|
| 27 |
+
_READBACK_PATH = Path(__file__).with_name("zenodo-readback.json")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def _configured_version_doi() -> str | None:
|
| 31 |
+
value = os.getenv("A11OY_VERSION_DOI", "").strip()
|
| 32 |
+
if not value or not _ZENODO_DOI_RE.fullmatch(value):
|
| 33 |
+
return None
|
| 34 |
+
if value in {CONCEPT_DOI, FORMAL_ARTIFACT_DOI}:
|
| 35 |
+
return None
|
| 36 |
+
return value
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def _configured_release_tag() -> str | None:
|
| 40 |
+
value = os.getenv("A11OY_RELEASE_TAG", "").strip()
|
| 41 |
+
return value if value == _EXPECTED_RELEASE_TAG else None
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def _verified_readback() -> dict[str, Any] | None:
|
| 45 |
+
try:
|
| 46 |
+
payload = json.loads(_READBACK_PATH.read_text(encoding="utf-8"))
|
| 47 |
+
except (OSError, ValueError, TypeError):
|
| 48 |
+
return None
|
| 49 |
+
if not isinstance(payload, dict) or payload.get("status") != "VERIFIED":
|
| 50 |
+
return None
|
| 51 |
+
if payload.get("software_version") != SOFTWARE_VERSION:
|
| 52 |
+
return None
|
| 53 |
+
if payload.get("release_tag") != _EXPECTED_RELEASE_TAG:
|
| 54 |
+
return None
|
| 55 |
+
doi = str(payload.get("doi") or "")
|
| 56 |
+
if not _ZENODO_DOI_RE.fullmatch(doi) or doi in {CONCEPT_DOI, FORMAL_ARTIFACT_DOI}:
|
| 57 |
+
return None
|
| 58 |
+
if not str(payload.get("metadata_sha256") or ""):
|
| 59 |
+
return None
|
| 60 |
+
return payload
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def release_identity() -> dict[str, Any]:
|
| 64 |
+
"""Return release identity without upgrading unverified state.
|
| 65 |
+
|
| 66 |
+
``A11OY_VERSION_DOI`` and ``A11OY_RELEASE_TAG`` are accepted only when both
|
| 67 |
+
have valid syntax. Their presence means CONFIGURED, not independently
|
| 68 |
+
VERIFIED; deployment or archive verification must establish resolution.
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
+
readback = _verified_readback()
|
| 72 |
+
version_doi = str(readback["doi"]) if readback else _configured_version_doi()
|
| 73 |
+
release_tag = str(readback["release_tag"]) if readback else _configured_release_tag()
|
| 74 |
+
configured = bool(version_doi and release_tag)
|
| 75 |
+
verified = bool(readback)
|
| 76 |
+
release_url = f"{REPOSITORY_URL}/releases/tag/{release_tag}" if configured else f"{REPOSITORY_URL}/releases"
|
| 77 |
+
|
| 78 |
+
return {
|
| 79 |
+
"name": SOFTWARE_NAME,
|
| 80 |
+
"version": SOFTWARE_VERSION,
|
| 81 |
+
"expected_release_tag": _EXPECTED_RELEASE_TAG,
|
| 82 |
+
"release_state": "VERIFIED" if verified else ("CONFIGURED_UNVERIFIED" if configured else "CANDIDATE"),
|
| 83 |
+
"release_tag": release_tag,
|
| 84 |
+
"release_url": release_url,
|
| 85 |
+
"surfaces": {
|
| 86 |
+
"canonical": CANONICAL_URL,
|
| 87 |
+
"legacy_alias": LEGACY_ALIAS,
|
| 88 |
+
"legacy_alias_policy": "PERMANENT_REDIRECT_TO_CANONICAL",
|
| 89 |
+
"repository": REPOSITORY_URL,
|
| 90 |
+
},
|
| 91 |
+
"doi": {
|
| 92 |
+
"concept": {
|
| 93 |
+
"value": CONCEPT_DOI,
|
| 94 |
+
"url": f"https://doi.org/{CONCEPT_DOI}",
|
| 95 |
+
"role": "ASSOCIATED_RESEARCH_PROGRAM",
|
| 96 |
+
},
|
| 97 |
+
"formal_artifacts": {
|
| 98 |
+
"value": FORMAL_ARTIFACT_DOI,
|
| 99 |
+
"url": f"https://doi.org/{FORMAL_ARTIFACT_DOI}",
|
| 100 |
+
"role": "EXISTING_FORMAL_ARTIFACT_RECORD",
|
| 101 |
+
},
|
| 102 |
+
"software_version": {
|
| 103 |
+
"value": version_doi,
|
| 104 |
+
"url": f"https://doi.org/{version_doi}" if version_doi else None,
|
| 105 |
+
"status": "VERIFIED" if verified else ("CONFIGURED_UNVERIFIED" if configured else "PENDING_ZENODO_READBACK"),
|
| 106 |
+
"readback": readback,
|
| 107 |
+
},
|
| 108 |
+
},
|
| 109 |
+
"honesty": {
|
| 110 |
+
"configured_is_operational": False,
|
| 111 |
+
"conjecture_promoted": False,
|
| 112 |
+
"doi_invented": False,
|
| 113 |
+
},
|
| 114 |
+
}
|
|
@@ -816,11 +816,11 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 816 |
n_before = len(app.router.routes)
|
| 817 |
|
| 818 |
@app.get(f"/api/{ns}/v1/waqay/doctrine", include_in_schema=False)
|
| 819 |
-
async def _doctrine()
|
| 820 |
return JSONResponse({"doctrine": DOCTRINE, "trust_ceiling": TRUST_CEILING})
|
| 821 |
|
| 822 |
@app.get(f"/api/{ns}/v1/waqay/demo", include_in_schema=False)
|
| 823 |
-
async def _demo(req: Request)
|
| 824 |
try:
|
| 825 |
bw = int(req.query_params.get("bits", "2"))
|
| 826 |
except Exception:
|
|
@@ -829,7 +829,7 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 829 |
return JSONResponse(demo(query=q, bit_width=bw if bw in (2, 4) else 2))
|
| 830 |
|
| 831 |
@app.post(f"/api/{ns}/v1/waqay/search", include_in_schema=False)
|
| 832 |
-
async def _search(req: Request)
|
| 833 |
try:
|
| 834 |
body = await req.json()
|
| 835 |
except Exception:
|
|
@@ -839,7 +839,7 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 839 |
return JSONResponse(demo(query=q, bit_width=bw if bw in (2, 4) else 2))
|
| 840 |
|
| 841 |
@app.get(f"/api/{ns}/v1/waqay/receipts", include_in_schema=False)
|
| 842 |
-
async def _receipts()
|
| 843 |
tail = _RECEIPTS[-20:]
|
| 844 |
return JSONResponse({"count": len(_RECEIPTS),
|
| 845 |
"receipts": [{"payload": r["payload"],
|
|
@@ -847,7 +847,7 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 847 |
for r in tail]})
|
| 848 |
|
| 849 |
@app.post(f"/api/{ns}/v1/waqay/verify", include_in_schema=False)
|
| 850 |
-
async def _verify(req: Request)
|
| 851 |
try:
|
| 852 |
body = await req.json()
|
| 853 |
except Exception:
|
|
@@ -856,7 +856,7 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 856 |
return JSONResponse(verify_receipt(env))
|
| 857 |
|
| 858 |
@app.get("/waqay", include_in_schema=False)
|
| 859 |
-
async def _page()
|
| 860 |
return HTMLResponse(_PAGE_HTML.replace("{NS}", ns))
|
| 861 |
|
| 862 |
# Move the WAQAY routes just appended (the tail beyond n_before) to the FRONT,
|
|
|
|
| 816 |
n_before = len(app.router.routes)
|
| 817 |
|
| 818 |
@app.get(f"/api/{ns}/v1/waqay/doctrine", include_in_schema=False)
|
| 819 |
+
async def _doctrine(): # noqa: ANN202
|
| 820 |
return JSONResponse({"doctrine": DOCTRINE, "trust_ceiling": TRUST_CEILING})
|
| 821 |
|
| 822 |
@app.get(f"/api/{ns}/v1/waqay/demo", include_in_schema=False)
|
| 823 |
+
async def _demo(req: Request): # noqa: ANN202
|
| 824 |
try:
|
| 825 |
bw = int(req.query_params.get("bits", "2"))
|
| 826 |
except Exception:
|
|
|
|
| 829 |
return JSONResponse(demo(query=q, bit_width=bw if bw in (2, 4) else 2))
|
| 830 |
|
| 831 |
@app.post(f"/api/{ns}/v1/waqay/search", include_in_schema=False)
|
| 832 |
+
async def _search(req: Request): # noqa: ANN202
|
| 833 |
try:
|
| 834 |
body = await req.json()
|
| 835 |
except Exception:
|
|
|
|
| 839 |
return JSONResponse(demo(query=q, bit_width=bw if bw in (2, 4) else 2))
|
| 840 |
|
| 841 |
@app.get(f"/api/{ns}/v1/waqay/receipts", include_in_schema=False)
|
| 842 |
+
async def _receipts(): # noqa: ANN202
|
| 843 |
tail = _RECEIPTS[-20:]
|
| 844 |
return JSONResponse({"count": len(_RECEIPTS),
|
| 845 |
"receipts": [{"payload": r["payload"],
|
|
|
|
| 847 |
for r in tail]})
|
| 848 |
|
| 849 |
@app.post(f"/api/{ns}/v1/waqay/verify", include_in_schema=False)
|
| 850 |
+
async def _verify(req: Request): # noqa: ANN202
|
| 851 |
try:
|
| 852 |
body = await req.json()
|
| 853 |
except Exception:
|
|
|
|
| 856 |
return JSONResponse(verify_receipt(env))
|
| 857 |
|
| 858 |
@app.get("/waqay", include_in_schema=False)
|
| 859 |
+
async def _page(): # noqa: ANN202
|
| 860 |
return HTMLResponse(_PAGE_HTML.replace("{NS}", ns))
|
| 861 |
|
| 862 |
# Move the WAQAY routes just appended (the tail beyond n_before) to the FRONT,
|
|
@@ -0,0 +1,875 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Yupaq governed computation plane.
|
| 3 |
+
|
| 4 |
+
Yupaq ("the one who counts") binds the existing A11oy numerical, quant,
|
| 5 |
+
formal, evidence, and trust organs behind one strict job contract. It is an
|
| 6 |
+
orchestrator, not a new calculator: every operation delegates to an existing
|
| 7 |
+
versioned implementation and retains that implementation's honesty label.
|
| 8 |
+
|
| 9 |
+
The public contract deliberately accepts no source code, expressions, paths,
|
| 10 |
+
URLs, packages, shell arguments, provider credentials, or arbitrary function
|
| 11 |
+
names. A completed job produces a canonical result digest, an optional DSSE
|
| 12 |
+
envelope, a Lake chain record, and OpenTelemetry-shaped timing spans. Missing
|
| 13 |
+
engines remain UNAVAILABLE and never receive synthetic proof or trust uplift.
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
from __future__ import annotations
|
| 17 |
+
|
| 18 |
+
import asyncio
|
| 19 |
+
import copy
|
| 20 |
+
import hashlib
|
| 21 |
+
import hmac
|
| 22 |
+
import json
|
| 23 |
+
import math
|
| 24 |
+
import os
|
| 25 |
+
import re
|
| 26 |
+
import threading
|
| 27 |
+
import time
|
| 28 |
+
from collections import OrderedDict
|
| 29 |
+
from contextlib import nullcontext
|
| 30 |
+
from datetime import datetime, timezone
|
| 31 |
+
from pathlib import Path
|
| 32 |
+
from typing import Any, Mapping, Sequence
|
| 33 |
+
|
| 34 |
+
try:
|
| 35 |
+
from fastapi import Request # noqa: F401
|
| 36 |
+
from fastapi.responses import JSONResponse # noqa: F401
|
| 37 |
+
except Exception: # pragma: no cover - register() is not called without FastAPI
|
| 38 |
+
Request = JSONResponse = Any # type: ignore
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
ROOT = Path(__file__).resolve().parent
|
| 42 |
+
JOB_SCHEMA = "szl.compute-job/v1"
|
| 43 |
+
RESULT_SCHEMA = "szl.compute-result/v1"
|
| 44 |
+
RECEIPT_SCHEMA = "szl.compute-receipt/v1"
|
| 45 |
+
PAYLOAD_TYPE = "application/vnd.szl.compute-receipt+json"
|
| 46 |
+
MAX_BODY_BYTES = 128 * 1024
|
| 47 |
+
MAX_OUTPUT_BYTES = 256 * 1024
|
| 48 |
+
MAX_RUNTIME_MS = 8_000
|
| 49 |
+
MAX_JOBS_IN_MEMORY = 256
|
| 50 |
+
MAX_PROCESS_BINDINGS = 4_096
|
| 51 |
+
ZERO_UPLIFT = {"proof_uplift": 0, "trust_uplift": 0}
|
| 52 |
+
JOB_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,95}$")
|
| 53 |
+
|
| 54 |
+
OPERATIONS = (
|
| 55 |
+
"formula.org_lambda.weighted_geomean",
|
| 56 |
+
"quant.sample.pipeline",
|
| 57 |
+
"quantum.qubo.exact_baseline",
|
| 58 |
+
"numerics.external.run",
|
| 59 |
+
"numerics.external.compare",
|
| 60 |
+
"proof.lean.inventory",
|
| 61 |
+
"formula.admission.inventory",
|
| 62 |
+
"brain.corpus.inventory",
|
| 63 |
+
"lake.evidence.inventory",
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
_STORE: "OrderedDict[tuple[str, str], dict[str, Any]]" = OrderedDict()
|
| 67 |
+
_REQUEST_BINDINGS: dict[tuple[str, str], str] = {}
|
| 68 |
+
_STORE_LOCK = threading.RLock()
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
class ContractError(ValueError):
|
| 72 |
+
"""A compute job violates the fixed, data-only contract."""
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
class AuthenticationError(PermissionError):
|
| 76 |
+
"""A compute route has no valid configured bearer authority."""
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
class BodyTooLarge(ContractError):
|
| 80 |
+
"""A request exceeded the compute plane's fixed pre-parse body limit."""
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def _authorize_request(request: Any) -> str:
|
| 84 |
+
"""Return a non-secret owner id for a configured compute bearer token.
|
| 85 |
+
|
| 86 |
+
The runtime stores only the expected SHA-256 in
|
| 87 |
+
``A11OY_COMPUTE_TOKEN_SHA256``. If it is absent, stateful compute routes
|
| 88 |
+
fail closed rather than becoming an unauthenticated public executor.
|
| 89 |
+
"""
|
| 90 |
+
expected = os.environ.get("A11OY_COMPUTE_TOKEN_SHA256", "").strip().lower()
|
| 91 |
+
if not re.fullmatch(r"[0-9a-f]{64}", expected):
|
| 92 |
+
raise AuthenticationError("compute authority is not configured")
|
| 93 |
+
authorization = (request.headers.get("authorization") or "").strip()
|
| 94 |
+
if not authorization.lower().startswith("bearer "):
|
| 95 |
+
raise AuthenticationError("missing compute bearer authority")
|
| 96 |
+
token = authorization.split(" ", 1)[1].strip()
|
| 97 |
+
observed = hashlib.sha256(token.encode("utf-8")).hexdigest()
|
| 98 |
+
if not hmac.compare_digest(observed, expected):
|
| 99 |
+
raise AuthenticationError("invalid compute bearer authority")
|
| 100 |
+
return f"sha256:{expected[:16]}"
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def canonical_json(value: Any) -> bytes:
|
| 104 |
+
return json.dumps(
|
| 105 |
+
value,
|
| 106 |
+
sort_keys=True,
|
| 107 |
+
separators=(",", ":"),
|
| 108 |
+
ensure_ascii=False,
|
| 109 |
+
allow_nan=False,
|
| 110 |
+
).encode("utf-8")
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def digest_json(value: Any) -> str:
|
| 114 |
+
return hashlib.sha256(canonical_json(value)).hexdigest()
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def _now_iso() -> str:
|
| 118 |
+
return datetime.now(timezone.utc).isoformat()
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def _mapping(value: Any, name: str) -> Mapping[str, Any]:
|
| 122 |
+
if not isinstance(value, Mapping):
|
| 123 |
+
raise ContractError(f"{name} must be an object")
|
| 124 |
+
return value
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def _strict(value: Mapping[str, Any], allowed: set[str], required: set[str], name: str) -> None:
|
| 128 |
+
extras = sorted(set(value) - allowed)
|
| 129 |
+
missing = sorted(required - set(value))
|
| 130 |
+
if extras:
|
| 131 |
+
raise ContractError(f"{name} has unsupported fields: {', '.join(extras)}")
|
| 132 |
+
if missing:
|
| 133 |
+
raise ContractError(f"{name} is missing fields: {', '.join(missing)}")
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def _finite(value: Any, name: str, minimum: float, maximum: float) -> float:
|
| 137 |
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
| 138 |
+
raise ContractError(f"{name} must be a finite number")
|
| 139 |
+
result = float(value)
|
| 140 |
+
if not math.isfinite(result) or not minimum <= result <= maximum:
|
| 141 |
+
raise ContractError(f"{name} must be between {minimum} and {maximum}")
|
| 142 |
+
return result
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def _integer(value: Any, name: str, minimum: int, maximum: int) -> int:
|
| 146 |
+
if isinstance(value, bool) or not isinstance(value, int) or not minimum <= value <= maximum:
|
| 147 |
+
raise ContractError(f"{name} must be an integer between {minimum} and {maximum}")
|
| 148 |
+
return value
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
def _json_object(path: Path, name: str) -> dict[str, Any]:
|
| 152 |
+
try:
|
| 153 |
+
value = json.loads(path.read_text(encoding="utf-8"))
|
| 154 |
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
| 155 |
+
raise ContractError(f"{name} is unavailable") from exc
|
| 156 |
+
if not isinstance(value, dict):
|
| 157 |
+
raise ContractError(f"{name} must be a JSON object")
|
| 158 |
+
return value
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def _file_receipt(path: Path) -> dict[str, Any]:
|
| 162 |
+
data = path.read_bytes()
|
| 163 |
+
return {
|
| 164 |
+
"path": path.relative_to(ROOT).as_posix(),
|
| 165 |
+
"bytes": len(data),
|
| 166 |
+
"sha256": hashlib.sha256(data).hexdigest(),
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def _parse_lambda_inputs(value: Mapping[str, Any]) -> dict[str, Any]:
|
| 171 |
+
_strict(value, {"axes", "weights"}, {"axes", "weights"}, "inputs")
|
| 172 |
+
axes = value["axes"]
|
| 173 |
+
weights = value["weights"]
|
| 174 |
+
if (
|
| 175 |
+
not isinstance(axes, Sequence)
|
| 176 |
+
or isinstance(axes, (str, bytes, bytearray))
|
| 177 |
+
or not 1 <= len(axes) <= 32
|
| 178 |
+
):
|
| 179 |
+
raise ContractError("inputs.axes must contain 1..32 scores")
|
| 180 |
+
if (
|
| 181 |
+
not isinstance(weights, Sequence)
|
| 182 |
+
or isinstance(weights, (str, bytes, bytearray))
|
| 183 |
+
or len(weights) != len(axes)
|
| 184 |
+
):
|
| 185 |
+
raise ContractError("inputs.weights must match inputs.axes")
|
| 186 |
+
parsed_axes = [_finite(item, f"inputs.axes[{index}]", 0.0, 1.0) for index, item in enumerate(axes)]
|
| 187 |
+
parsed_weights = [
|
| 188 |
+
_finite(item, f"inputs.weights[{index}]", 0.0, 1.0)
|
| 189 |
+
for index, item in enumerate(weights)
|
| 190 |
+
]
|
| 191 |
+
if sum(parsed_weights) <= 0.0:
|
| 192 |
+
raise ContractError("inputs.weights must have a positive sum")
|
| 193 |
+
return {"axes": parsed_axes, "weights": parsed_weights}
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
def _parse_inputs(operation: str, raw: Mapping[str, Any]) -> dict[str, Any]:
|
| 197 |
+
value = dict(raw)
|
| 198 |
+
if operation == "formula.org_lambda.weighted_geomean":
|
| 199 |
+
return _parse_lambda_inputs(value)
|
| 200 |
+
if operation == "quant.sample.pipeline":
|
| 201 |
+
_strict(value, {"stress", "gamma", "kappa"}, {"stress", "gamma", "kappa"}, "inputs")
|
| 202 |
+
if not isinstance(value["stress"], bool):
|
| 203 |
+
raise ContractError("inputs.stress must be a boolean")
|
| 204 |
+
return {
|
| 205 |
+
"stress": value["stress"],
|
| 206 |
+
"gamma": _finite(value["gamma"], "inputs.gamma", 0.0, 10.0),
|
| 207 |
+
"kappa": _finite(value["kappa"], "inputs.kappa", 0.0, 10.0),
|
| 208 |
+
}
|
| 209 |
+
if operation == "quantum.qubo.exact_baseline":
|
| 210 |
+
_strict(value, {"request"}, {"request"}, "inputs")
|
| 211 |
+
return {"request": dict(_mapping(value["request"], "inputs.request"))}
|
| 212 |
+
if operation == "numerics.external.run":
|
| 213 |
+
_strict(value, {"engine", "request"}, {"engine", "request"}, "inputs")
|
| 214 |
+
if value["engine"] not in ("octave", "matlab"):
|
| 215 |
+
raise ContractError("inputs.engine must be octave or matlab")
|
| 216 |
+
return {"engine": value["engine"], "request": dict(_mapping(value["request"], "inputs.request"))}
|
| 217 |
+
if operation == "numerics.external.compare":
|
| 218 |
+
_strict(value, {"request"}, {"request"}, "inputs")
|
| 219 |
+
return {"request": dict(_mapping(value["request"], "inputs.request"))}
|
| 220 |
+
if operation in {
|
| 221 |
+
"proof.lean.inventory",
|
| 222 |
+
"formula.admission.inventory",
|
| 223 |
+
"brain.corpus.inventory",
|
| 224 |
+
"lake.evidence.inventory",
|
| 225 |
+
}:
|
| 226 |
+
_strict(value, set(), set(), "inputs")
|
| 227 |
+
return {}
|
| 228 |
+
raise ContractError("unsupported operation")
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
def parse_job(payload: Mapping[str, Any]) -> dict[str, Any]:
|
| 232 |
+
obj = _mapping(payload, "job")
|
| 233 |
+
allowed = {"schema", "job_id", "operation", "inputs", "resource_budget"}
|
| 234 |
+
_strict(obj, allowed, allowed, "job")
|
| 235 |
+
if obj["schema"] != JOB_SCHEMA:
|
| 236 |
+
raise ContractError(f"schema must be {JOB_SCHEMA}")
|
| 237 |
+
job_id = obj["job_id"]
|
| 238 |
+
if not isinstance(job_id, str) or not JOB_ID_RE.fullmatch(job_id):
|
| 239 |
+
raise ContractError("job_id must be a bounded identifier")
|
| 240 |
+
operation = obj["operation"]
|
| 241 |
+
if operation not in OPERATIONS:
|
| 242 |
+
raise ContractError("operation is not registered")
|
| 243 |
+
budget = _mapping(obj["resource_budget"], "resource_budget")
|
| 244 |
+
_strict(
|
| 245 |
+
budget,
|
| 246 |
+
{"max_runtime_ms", "max_output_bytes"},
|
| 247 |
+
{"max_runtime_ms", "max_output_bytes"},
|
| 248 |
+
"resource_budget",
|
| 249 |
+
)
|
| 250 |
+
return {
|
| 251 |
+
"schema": JOB_SCHEMA,
|
| 252 |
+
"job_id": job_id,
|
| 253 |
+
"operation": operation,
|
| 254 |
+
"inputs": _parse_inputs(operation, _mapping(obj["inputs"], "inputs")),
|
| 255 |
+
"resource_budget": {
|
| 256 |
+
"max_runtime_ms": _integer(budget["max_runtime_ms"], "resource_budget.max_runtime_ms", 1, MAX_RUNTIME_MS),
|
| 257 |
+
"max_output_bytes": _integer(budget["max_output_bytes"], "resource_budget.max_output_bytes", 1_024, MAX_OUTPUT_BYTES),
|
| 258 |
+
},
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def _lambda_job(inputs: Mapping[str, Any]) -> dict[str, Any]:
|
| 263 |
+
from szl_org_lambda import weighted_geomean
|
| 264 |
+
|
| 265 |
+
value = weighted_geomean(inputs["axes"], inputs["weights"])
|
| 266 |
+
return {
|
| 267 |
+
"value": value,
|
| 268 |
+
"label": "ADVISORY",
|
| 269 |
+
"runtime_binding": "szl_org_lambda.weighted_geomean",
|
| 270 |
+
"formula_namespace": "org-lambda.weighted-geomean",
|
| 271 |
+
"zero_absorption": any(item == 0.0 for item in inputs["axes"]),
|
| 272 |
+
"uniqueness": "CONJECTURE_1_OPEN",
|
| 273 |
+
"proof_transfer": "DENIED_NAMESPACE_SCOPED",
|
| 274 |
+
**ZERO_UPLIFT,
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
def _quant_job(inputs: Mapping[str, Any]) -> dict[str, Any]:
|
| 279 |
+
from szl_gpu_quant import run_pipeline
|
| 280 |
+
|
| 281 |
+
return run_pipeline(
|
| 282 |
+
stress=inputs["stress"],
|
| 283 |
+
gamma=inputs["gamma"],
|
| 284 |
+
kappa=inputs["kappa"],
|
| 285 |
+
)
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
def _quantum_job(inputs: Mapping[str, Any]) -> dict[str, Any]:
|
| 289 |
+
from szl_quantum_utility import run_with_receipt
|
| 290 |
+
|
| 291 |
+
return run_with_receipt("QUBO_EXACT_BASELINE", inputs["request"])
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
def _numerics_run(inputs: Mapping[str, Any], budget: Mapping[str, int]) -> dict[str, Any]:
|
| 295 |
+
from szl_numerics_adapter import run_engine
|
| 296 |
+
|
| 297 |
+
timeout = max(1, min(8, math.ceil(budget["max_runtime_ms"] / 1_000)))
|
| 298 |
+
return run_engine(inputs["engine"], inputs["request"], timeout_seconds=timeout)
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
def _numerics_compare(inputs: Mapping[str, Any]) -> dict[str, Any]:
|
| 302 |
+
from szl_numerics_adapter import compare_engines
|
| 303 |
+
|
| 304 |
+
return compare_engines(inputs["request"])
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def _lean_inventory() -> dict[str, Any]:
|
| 308 |
+
path = ROOT / "proofs" / "lean-theorem-tree.json"
|
| 309 |
+
source = _json_object(path, "Lean theorem inventory")
|
| 310 |
+
meta = source.get("meta") or {}
|
| 311 |
+
return {
|
| 312 |
+
"state": "INVENTORY_ONLY_NOT_FRESH_KERNEL_EXECUTION",
|
| 313 |
+
"toolchain": "Lean 4.13.0 + mathlib 4.13.0 (repository pin)",
|
| 314 |
+
"commit": str(meta.get("commit") or "UNKNOWN"),
|
| 315 |
+
"total_declarations": int(meta.get("total_declarations") or 0),
|
| 316 |
+
"inventory": _file_receipt(path),
|
| 317 |
+
"kernel_execution_this_job": False,
|
| 318 |
+
**ZERO_UPLIFT,
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
def _formula_inventory() -> dict[str, Any]:
|
| 323 |
+
path = ROOT / "research" / "formula-training-admission" / "admission-manifest.json"
|
| 324 |
+
source = _json_object(path, "formula admission manifest")
|
| 325 |
+
summary = source.get("decision_summary") or {}
|
| 326 |
+
thesis = ((source.get("source_snapshot") or {}).get("thesis") or {})
|
| 327 |
+
return {
|
| 328 |
+
"state": source.get("status", "UNKNOWN"),
|
| 329 |
+
"admission": summary.get("training_admission", "UNKNOWN"),
|
| 330 |
+
"crosswalk_rows": summary.get("formula_crosswalk_rows", 0),
|
| 331 |
+
"holdout_rows": summary.get("holdout_rows", 0),
|
| 332 |
+
"train_rows": summary.get("train_rows", 0),
|
| 333 |
+
"resolved_status_counts": summary.get("resolved_status_counts", {}),
|
| 334 |
+
"thesis_extracted_formula_count": thesis.get("extracted_formula_count", 0),
|
| 335 |
+
"requested_200_status": "NOT_VERIFIED_BY_CURRENT_VERSIONED_SOURCES",
|
| 336 |
+
"manifest": _file_receipt(path),
|
| 337 |
+
**ZERO_UPLIFT,
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
def _brain_inventory() -> dict[str, Any]:
|
| 342 |
+
path = ROOT / "model_release" / "m1" / "corpus-ingestion-manifest.json"
|
| 343 |
+
source = _json_object(path, "Brain corpus manifest")
|
| 344 |
+
coverage = source.get("coverage") or {}
|
| 345 |
+
return {
|
| 346 |
+
"state": "RETRIEVAL_AND_EVAL_AVAILABLE_TRAINING_QUARANTINED",
|
| 347 |
+
"raw_nodes": int(coverage.get("node_decisions_total") or 0),
|
| 348 |
+
"distinct_artifacts": int(coverage.get("distinct_artifacts") or 0),
|
| 349 |
+
"training_eligible_nodes": int(coverage.get("training_eligible_nodes") or 0),
|
| 350 |
+
"missing_item_level_license_nodes": int(coverage.get("missing_item_level_license_nodes") or 0),
|
| 351 |
+
"missing_source_timestamp_nodes": int(coverage.get("missing_source_timestamp_nodes") or 0),
|
| 352 |
+
"manifest": _file_receipt(path),
|
| 353 |
+
**ZERO_UPLIFT,
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
def _lake_inventory() -> dict[str, Any]:
|
| 358 |
+
path = ROOT / "data" / "szl-lake" / "evidence-manifest.json"
|
| 359 |
+
source = _json_object(path, "SZL Lake evidence manifest")
|
| 360 |
+
entries = source.get("entries") or []
|
| 361 |
+
return {
|
| 362 |
+
"state": "EVIDENCE_AND_RECEIPT_SUBSTRATE",
|
| 363 |
+
"entry_count": len(entries),
|
| 364 |
+
"proof_statuses": sorted(
|
| 365 |
+
{
|
| 366 |
+
str(((entry.get("artifact_receipt") or {}).get("proof_status") or "UNKNOWN"))
|
| 367 |
+
for entry in entries
|
| 368 |
+
if isinstance(entry, Mapping)
|
| 369 |
+
}
|
| 370 |
+
),
|
| 371 |
+
"manifest": _file_receipt(path),
|
| 372 |
+
**ZERO_UPLIFT,
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
def _execute(operation: str, inputs: Mapping[str, Any], budget: Mapping[str, int]) -> dict[str, Any]:
|
| 377 |
+
if operation == "formula.org_lambda.weighted_geomean":
|
| 378 |
+
return _lambda_job(inputs)
|
| 379 |
+
if operation == "quant.sample.pipeline":
|
| 380 |
+
return _quant_job(inputs)
|
| 381 |
+
if operation == "quantum.qubo.exact_baseline":
|
| 382 |
+
return _quantum_job(inputs)
|
| 383 |
+
if operation == "numerics.external.run":
|
| 384 |
+
return _numerics_run(inputs, budget)
|
| 385 |
+
if operation == "numerics.external.compare":
|
| 386 |
+
return _numerics_compare(inputs)
|
| 387 |
+
if operation == "proof.lean.inventory":
|
| 388 |
+
return _lean_inventory()
|
| 389 |
+
if operation == "formula.admission.inventory":
|
| 390 |
+
return _formula_inventory()
|
| 391 |
+
if operation == "brain.corpus.inventory":
|
| 392 |
+
return _brain_inventory()
|
| 393 |
+
if operation == "lake.evidence.inventory":
|
| 394 |
+
return _lake_inventory()
|
| 395 |
+
raise ContractError("operation is not registered")
|
| 396 |
+
|
| 397 |
+
|
| 398 |
+
def _state_for(operation: str, output: Mapping[str, Any]) -> tuple[str, str]:
|
| 399 |
+
if operation == "numerics.external.run" and output.get("state") == "UNAVAILABLE":
|
| 400 |
+
return "UNAVAILABLE", "UNKNOWN"
|
| 401 |
+
if operation == "numerics.external.compare" and output.get("comparison_state") == "UNAVAILABLE":
|
| 402 |
+
return "UNAVAILABLE", "UNKNOWN"
|
| 403 |
+
if operation == "quant.sample.pipeline":
|
| 404 |
+
return "COMPLETED", "SAMPLE"
|
| 405 |
+
if operation.startswith("proof."):
|
| 406 |
+
return "COMPLETED", "INVENTORY"
|
| 407 |
+
if operation.startswith(("formula.admission", "brain.", "lake.")):
|
| 408 |
+
return "COMPLETED", "VERSIONED_LOCAL_EVIDENCE"
|
| 409 |
+
if operation.startswith("quantum."):
|
| 410 |
+
return "COMPLETED", "MEASURED_CLASSICAL_BASELINE"
|
| 411 |
+
return "COMPLETED", "COMPUTED_ADVISORY"
|
| 412 |
+
|
| 413 |
+
|
| 414 |
+
def _span(name: str, operation: str):
|
| 415 |
+
try:
|
| 416 |
+
from szl_observability import span
|
| 417 |
+
|
| 418 |
+
return span(name, operation=operation, component="yupaq-compute")
|
| 419 |
+
except Exception:
|
| 420 |
+
return nullcontext()
|
| 421 |
+
|
| 422 |
+
|
| 423 |
+
def _sign_receipt(body: Mapping[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
|
| 424 |
+
try:
|
| 425 |
+
from szl_dsse import sign_payload, verify_envelope
|
| 426 |
+
|
| 427 |
+
envelope = sign_payload(dict(body), PAYLOAD_TYPE)
|
| 428 |
+
verification = verify_envelope(envelope)
|
| 429 |
+
return envelope, verification
|
| 430 |
+
except Exception as exc:
|
| 431 |
+
return (
|
| 432 |
+
{
|
| 433 |
+
"payloadType": PAYLOAD_TYPE,
|
| 434 |
+
"payload": "",
|
| 435 |
+
"signatures": [],
|
| 436 |
+
"signed": False,
|
| 437 |
+
"honesty": f"UNSIGNED: DSSE unavailable ({type(exc).__name__})",
|
| 438 |
+
},
|
| 439 |
+
{"verified": False, "reason": "DSSE_UNAVAILABLE"},
|
| 440 |
+
)
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
def _append_to_lake(record: Mapping[str, Any]) -> dict[str, Any]:
|
| 444 |
+
try:
|
| 445 |
+
from szl_lake_store import get_default_ledger
|
| 446 |
+
|
| 447 |
+
return get_default_ledger().append(dict(record))
|
| 448 |
+
except Exception as exc:
|
| 449 |
+
return {
|
| 450 |
+
"accepted": False,
|
| 451 |
+
"duplicate": False,
|
| 452 |
+
"state": "UNAVAILABLE",
|
| 453 |
+
"reason": type(exc).__name__,
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def _lookup_memory(owner_id: str, job_id: str) -> dict[str, Any] | None:
|
| 458 |
+
key = (owner_id, job_id)
|
| 459 |
+
with _STORE_LOCK:
|
| 460 |
+
found = _STORE.get(key)
|
| 461 |
+
if found is None:
|
| 462 |
+
return None
|
| 463 |
+
_STORE.move_to_end(key)
|
| 464 |
+
return copy.deepcopy(found)
|
| 465 |
+
|
| 466 |
+
|
| 467 |
+
def _remember(owner_id: str, job: Mapping[str, Any]) -> None:
|
| 468 |
+
key = (owner_id, str(job["job_id"]))
|
| 469 |
+
with _STORE_LOCK:
|
| 470 |
+
_STORE[key] = copy.deepcopy(dict(job))
|
| 471 |
+
_STORE.move_to_end(key)
|
| 472 |
+
while len(_STORE) > MAX_JOBS_IN_MEMORY:
|
| 473 |
+
_STORE.popitem(last=False)
|
| 474 |
+
|
| 475 |
+
|
| 476 |
+
def run_job(
|
| 477 |
+
payload: Mapping[str, Any],
|
| 478 |
+
*,
|
| 479 |
+
persist: bool = True,
|
| 480 |
+
owner_id: str = "local-direct",
|
| 481 |
+
) -> dict[str, Any]:
|
| 482 |
+
"""Execute one strict, bounded job and return its result plus receipts."""
|
| 483 |
+
|
| 484 |
+
request = parse_job(payload)
|
| 485 |
+
request_sha256 = digest_json(request)
|
| 486 |
+
owner = str(owner_id or "").strip()
|
| 487 |
+
if not owner or len(owner) > 96:
|
| 488 |
+
raise ContractError("owner_id must be a bounded non-empty identifier")
|
| 489 |
+
key = (owner, request["job_id"])
|
| 490 |
+
with _STORE_LOCK:
|
| 491 |
+
existing = _STORE.get(key)
|
| 492 |
+
if existing is not None:
|
| 493 |
+
if existing["request_sha256"] != request_sha256:
|
| 494 |
+
raise ContractError("job_id is already bound to a different request")
|
| 495 |
+
replay = copy.deepcopy(existing)
|
| 496 |
+
replay["idempotent_replay"] = True
|
| 497 |
+
return replay
|
| 498 |
+
prior = _REQUEST_BINDINGS.get(key)
|
| 499 |
+
if prior is not None:
|
| 500 |
+
if prior != request_sha256:
|
| 501 |
+
raise ContractError("job_id is already bound to a different request")
|
| 502 |
+
raise ContractError("job_id is already in progress or retained by the replay guard")
|
| 503 |
+
if len(_REQUEST_BINDINGS) >= MAX_PROCESS_BINDINGS:
|
| 504 |
+
raise ContractError("process-local replay guard is at capacity")
|
| 505 |
+
_REQUEST_BINDINGS[key] = request_sha256
|
| 506 |
+
|
| 507 |
+
try:
|
| 508 |
+
started = time.perf_counter()
|
| 509 |
+
with _span("yupaq.compute", request["operation"]):
|
| 510 |
+
output = _execute(request["operation"], request["inputs"], request["resource_budget"])
|
| 511 |
+
duration_ms = round((time.perf_counter() - started) * 1_000, 3)
|
| 512 |
+
except Exception:
|
| 513 |
+
with _STORE_LOCK:
|
| 514 |
+
_REQUEST_BINDINGS.pop(key, None)
|
| 515 |
+
raise
|
| 516 |
+
|
| 517 |
+
output_bytes = canonical_json(output)
|
| 518 |
+
if len(output_bytes) > request["resource_budget"]["max_output_bytes"]:
|
| 519 |
+
state = "FAILED"
|
| 520 |
+
evidence_label = "OUTPUT_BUDGET_EXCEEDED"
|
| 521 |
+
output = {
|
| 522 |
+
"error": "output exceeded the declared byte budget",
|
| 523 |
+
"observed_output_bytes": len(output_bytes),
|
| 524 |
+
}
|
| 525 |
+
else:
|
| 526 |
+
state, evidence_label = _state_for(request["operation"], output)
|
| 527 |
+
if duration_ms > request["resource_budget"]["max_runtime_ms"]:
|
| 528 |
+
state = "FAILED"
|
| 529 |
+
evidence_label = "RUNTIME_BUDGET_EXCEEDED"
|
| 530 |
+
|
| 531 |
+
result = {
|
| 532 |
+
"schema": RESULT_SCHEMA,
|
| 533 |
+
"job_id": request["job_id"],
|
| 534 |
+
"operation": request["operation"],
|
| 535 |
+
"state": state,
|
| 536 |
+
"evidence_label": evidence_label,
|
| 537 |
+
"request_sha256": request_sha256,
|
| 538 |
+
"duration_ms": duration_ms,
|
| 539 |
+
"output": output,
|
| 540 |
+
"resource_budget": request["resource_budget"],
|
| 541 |
+
"runtime_budget_enforcement": "POST_HOC_EXCEPT_ENGINE_SPECIFIC_TIMEOUT",
|
| 542 |
+
"arbitrary_code_allowed": False,
|
| 543 |
+
"network_requested": False,
|
| 544 |
+
**ZERO_UPLIFT,
|
| 545 |
+
}
|
| 546 |
+
result_sha256 = digest_json(result)
|
| 547 |
+
receipt_body = {
|
| 548 |
+
"schema": RECEIPT_SCHEMA,
|
| 549 |
+
"organ": "yupaq-compute",
|
| 550 |
+
"owner_id": owner,
|
| 551 |
+
"job_id": request["job_id"],
|
| 552 |
+
"operation": request["operation"],
|
| 553 |
+
"request_sha256": request_sha256,
|
| 554 |
+
"result_sha256": result_sha256,
|
| 555 |
+
"code_commit": os.environ.get("A11OY_GIT_COMMIT", "UNKNOWN"),
|
| 556 |
+
"trace_id": os.environ.get("A11OY_TRACE_ID", "UNKNOWN"),
|
| 557 |
+
"created_at": _now_iso(),
|
| 558 |
+
"state": state,
|
| 559 |
+
"evidence_label": evidence_label,
|
| 560 |
+
"lambda_uniqueness": "CONJECTURE_1_OPEN",
|
| 561 |
+
**ZERO_UPLIFT,
|
| 562 |
+
}
|
| 563 |
+
receipt_body["receipt_sha256"] = digest_json(receipt_body)
|
| 564 |
+
dsse, dsse_verification = _sign_receipt(receipt_body)
|
| 565 |
+
response = {
|
| 566 |
+
"job_id": request["job_id"],
|
| 567 |
+
"owner_id": owner,
|
| 568 |
+
"request": request,
|
| 569 |
+
"request_sha256": request_sha256,
|
| 570 |
+
"result": result,
|
| 571 |
+
"result_sha256": result_sha256,
|
| 572 |
+
"receipt": receipt_body,
|
| 573 |
+
"dsse": dsse,
|
| 574 |
+
"dsse_verification": dsse_verification,
|
| 575 |
+
"idempotent_replay": False,
|
| 576 |
+
}
|
| 577 |
+
if persist:
|
| 578 |
+
response["lake"] = _append_to_lake(
|
| 579 |
+
{
|
| 580 |
+
"organ": "yupaq-compute",
|
| 581 |
+
"action": "compute.job",
|
| 582 |
+
"ts": receipt_body["created_at"],
|
| 583 |
+
"job_id": request["job_id"],
|
| 584 |
+
"request_sha256": request_sha256,
|
| 585 |
+
"result_sha256": result_sha256,
|
| 586 |
+
"receipt": receipt_body,
|
| 587 |
+
"dsse": dsse,
|
| 588 |
+
}
|
| 589 |
+
)
|
| 590 |
+
else:
|
| 591 |
+
response["lake"] = {"state": "NOT_REQUESTED"}
|
| 592 |
+
_remember(owner, response)
|
| 593 |
+
return copy.deepcopy(response)
|
| 594 |
+
|
| 595 |
+
|
| 596 |
+
def get_job(job_id: str, *, owner_id: str = "local-direct") -> dict[str, Any] | None:
|
| 597 |
+
if not JOB_ID_RE.fullmatch(job_id):
|
| 598 |
+
raise ContractError("job_id must be a bounded identifier")
|
| 599 |
+
return _lookup_memory(owner_id, job_id)
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
def verify_job_record(value: Mapping[str, Any]) -> dict[str, Any]:
|
| 603 |
+
obj = _mapping(value, "job record")
|
| 604 |
+
required = {
|
| 605 |
+
"job_id", "owner_id", "request", "request_sha256", "result",
|
| 606 |
+
"result_sha256", "receipt", "dsse",
|
| 607 |
+
}
|
| 608 |
+
missing = sorted(required - set(obj))
|
| 609 |
+
if missing:
|
| 610 |
+
raise ContractError(f"job record is missing fields: {', '.join(missing)}")
|
| 611 |
+
request_obj = _mapping(obj["request"], "request")
|
| 612 |
+
result_obj = _mapping(obj["result"], "result")
|
| 613 |
+
request_match = digest_json(request_obj) == obj["request_sha256"]
|
| 614 |
+
result_match = digest_json(result_obj) == obj["result_sha256"]
|
| 615 |
+
receipt = _mapping(obj["receipt"], "receipt")
|
| 616 |
+
receipt_material = dict(receipt)
|
| 617 |
+
claimed_receipt_sha256 = receipt_material.pop("receipt_sha256", None)
|
| 618 |
+
receipt_digest_match = (
|
| 619 |
+
isinstance(claimed_receipt_sha256, str)
|
| 620 |
+
and digest_json(receipt_material) == claimed_receipt_sha256
|
| 621 |
+
)
|
| 622 |
+
schema_match = (
|
| 623 |
+
request_obj.get("schema") == JOB_SCHEMA
|
| 624 |
+
and result_obj.get("schema") == RESULT_SCHEMA
|
| 625 |
+
and receipt.get("schema") == RECEIPT_SCHEMA
|
| 626 |
+
)
|
| 627 |
+
semantic_links = (
|
| 628 |
+
receipt.get("owner_id") == obj.get("owner_id")
|
| 629 |
+
and receipt.get("job_id") == obj.get("job_id")
|
| 630 |
+
== request_obj.get("job_id")
|
| 631 |
+
== result_obj.get("job_id")
|
| 632 |
+
and receipt.get("operation") == request_obj.get("operation")
|
| 633 |
+
== result_obj.get("operation")
|
| 634 |
+
and receipt.get("state") == result_obj.get("state")
|
| 635 |
+
and receipt.get("evidence_label") == result_obj.get("evidence_label")
|
| 636 |
+
and result_obj.get("request_sha256") == obj.get("request_sha256")
|
| 637 |
+
)
|
| 638 |
+
receipt_links = (
|
| 639 |
+
receipt.get("request_sha256") == obj["request_sha256"]
|
| 640 |
+
and receipt.get("result_sha256") == obj["result_sha256"]
|
| 641 |
+
)
|
| 642 |
+
try:
|
| 643 |
+
from szl_dsse import verify_envelope
|
| 644 |
+
|
| 645 |
+
dsse = verify_envelope(dict(_mapping(obj["dsse"], "dsse")))
|
| 646 |
+
except Exception:
|
| 647 |
+
dsse = {"verified": False, "reason": "DSSE_UNAVAILABLE"}
|
| 648 |
+
payload_match = dsse.get("payload_decoded") == dict(receipt)
|
| 649 |
+
return {
|
| 650 |
+
"valid": bool(
|
| 651 |
+
request_match
|
| 652 |
+
and result_match
|
| 653 |
+
and receipt_links
|
| 654 |
+
and receipt_digest_match
|
| 655 |
+
and schema_match
|
| 656 |
+
and semantic_links
|
| 657 |
+
and payload_match
|
| 658 |
+
and dsse.get("verified")
|
| 659 |
+
),
|
| 660 |
+
"request_hash_match": request_match,
|
| 661 |
+
"result_hash_match": result_match,
|
| 662 |
+
"receipt_links_match": receipt_links,
|
| 663 |
+
"receipt_digest_match": receipt_digest_match,
|
| 664 |
+
"schema_match": schema_match,
|
| 665 |
+
"semantic_links_match": semantic_links,
|
| 666 |
+
"dsse_payload_match": payload_match,
|
| 667 |
+
"signature_verified": bool(dsse.get("verified")),
|
| 668 |
+
"unsigned_records_are_valid": False,
|
| 669 |
+
}
|
| 670 |
+
|
| 671 |
+
|
| 672 |
+
def capabilities() -> dict[str, Any]:
|
| 673 |
+
try:
|
| 674 |
+
from szl_numerics_adapter import engine_status
|
| 675 |
+
|
| 676 |
+
numerics = engine_status()
|
| 677 |
+
except Exception:
|
| 678 |
+
numerics = {"mode": "UNAVAILABLE", "substrate_evidence": "UNKNOWN", **ZERO_UPLIFT}
|
| 679 |
+
brain = _brain_inventory()
|
| 680 |
+
formulas = _formula_inventory()
|
| 681 |
+
lean = _lean_inventory()
|
| 682 |
+
return {
|
| 683 |
+
"schema": "szl.compute-capabilities/v1",
|
| 684 |
+
"name": "Yupaq Governed Computation Plane",
|
| 685 |
+
"mode": "BOUNDED_TYPED_OPERATIONS_ONLY",
|
| 686 |
+
"operations": list(OPERATIONS),
|
| 687 |
+
"lanes": {
|
| 688 |
+
"quant": "CPU_REFERENCE_SAMPLE_ONLY",
|
| 689 |
+
"quantum_utility": "CLASSICAL_BASELINE_PROPOSAL_ONLY",
|
| 690 |
+
"numerics": numerics,
|
| 691 |
+
"lean_mathlib": lean,
|
| 692 |
+
"formula_registry": formulas,
|
| 693 |
+
"brain": brain,
|
| 694 |
+
"szl_lake": "BEST_EFFORT_LOCAL_KHIPU_APPEND_REDEPLOY_DURABILITY_NOT_VERIFIED",
|
| 695 |
+
"ouroboros": "ORCHESTRATION_LOOP_OUTSIDE_WEIGHTS",
|
| 696 |
+
"codex_workers": "PROPOSAL_BUILD_TEST_REVIEW_WITH_SIGNED_HANDOFFS",
|
| 697 |
+
"invariant": "NOT_WIRED_TO_RUN_JOB",
|
| 698 |
+
"lambda": "ADVISORY_CONJECTURE_1_OPEN",
|
| 699 |
+
},
|
| 700 |
+
"formula_accounting": {
|
| 701 |
+
"requested_200": "NOT_VERIFIED",
|
| 702 |
+
"thesis_extracted": formulas["thesis_extracted_formula_count"],
|
| 703 |
+
"crosswalk_rows": formulas["crosswalk_rows"],
|
| 704 |
+
"holdout_rows": formulas["holdout_rows"],
|
| 705 |
+
"train_rows": formulas["train_rows"],
|
| 706 |
+
"lean_declarations": lean["total_declarations"],
|
| 707 |
+
},
|
| 708 |
+
"brain_nodes": brain["raw_nodes"],
|
| 709 |
+
"brain_nodes_in_gradients": brain["training_eligible_nodes"],
|
| 710 |
+
"arbitrary_code_allowed": False,
|
| 711 |
+
"arbitrary_urls_allowed": False,
|
| 712 |
+
"model_weight_role": "MODEL_PROPOSES_TYPED_JOB; PLANE_VALIDATES_AND_EXECUTES",
|
| 713 |
+
"authorization": {
|
| 714 |
+
"stateful_routes_require_bearer": True,
|
| 715 |
+
"configured": bool(re.fullmatch(
|
| 716 |
+
r"[0-9a-f]{64}",
|
| 717 |
+
os.environ.get("A11OY_COMPUTE_TOKEN_SHA256", "").strip().lower(),
|
| 718 |
+
)),
|
| 719 |
+
"secret_name": "A11OY_COMPUTE_TOKEN_SHA256",
|
| 720 |
+
"owner_isolation": "TOKEN_SHA256_PREFIX",
|
| 721 |
+
"replay_scope": "PROCESS_LOCAL_BOUNDED",
|
| 722 |
+
},
|
| 723 |
+
**ZERO_UPLIFT,
|
| 724 |
+
}
|
| 725 |
+
|
| 726 |
+
|
| 727 |
+
async def _bounded_body(request: Any) -> dict[str, Any]:
|
| 728 |
+
declared = request.headers.get("content-length")
|
| 729 |
+
if declared is not None:
|
| 730 |
+
try:
|
| 731 |
+
size = int(declared)
|
| 732 |
+
except ValueError as exc:
|
| 733 |
+
raise ContractError("content-length must be a non-negative integer") from exc
|
| 734 |
+
if size < 0 or size > MAX_BODY_BYTES:
|
| 735 |
+
raise BodyTooLarge("request body exceeds 128 KiB")
|
| 736 |
+
data = bytearray()
|
| 737 |
+
async for chunk in request.stream():
|
| 738 |
+
if len(data) + len(chunk) > MAX_BODY_BYTES:
|
| 739 |
+
raise BodyTooLarge("request body exceeds 128 KiB")
|
| 740 |
+
data.extend(chunk)
|
| 741 |
+
try:
|
| 742 |
+
value = json.loads(bytes(data).decode("utf-8"))
|
| 743 |
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
| 744 |
+
raise ContractError("request body must be one JSON object") from exc
|
| 745 |
+
if not isinstance(value, dict):
|
| 746 |
+
raise ContractError("request body must be one JSON object")
|
| 747 |
+
return value
|
| 748 |
+
|
| 749 |
+
|
| 750 |
+
def register(app: Any, ns: str = "a11oy") -> dict[str, Any]:
|
| 751 |
+
"""Register the computation plane before proxy and SPA catch-alls."""
|
| 752 |
+
|
| 753 |
+
from fastapi import Request
|
| 754 |
+
from fastapi.responses import JSONResponse
|
| 755 |
+
|
| 756 |
+
prefix = f"/api/{ns}/v1/compute"
|
| 757 |
+
|
| 758 |
+
@app.get(f"{prefix}/capabilities")
|
| 759 |
+
async def compute_capabilities() -> JSONResponse:
|
| 760 |
+
return JSONResponse(capabilities())
|
| 761 |
+
|
| 762 |
+
@app.post(f"{prefix}/jobs")
|
| 763 |
+
async def compute_jobs(request: Request) -> JSONResponse:
|
| 764 |
+
try:
|
| 765 |
+
owner_id = _authorize_request(request)
|
| 766 |
+
except AuthenticationError as exc:
|
| 767 |
+
status = 503 if "not configured" in str(exc) else 401
|
| 768 |
+
return JSONResponse(
|
| 769 |
+
{"state": "UNAVAILABLE" if status == 503 else "UNAUTHORIZED",
|
| 770 |
+
"error": str(exc), **ZERO_UPLIFT},
|
| 771 |
+
status_code=status,
|
| 772 |
+
)
|
| 773 |
+
try:
|
| 774 |
+
payload = await _bounded_body(request)
|
| 775 |
+
record = await asyncio.to_thread(
|
| 776 |
+
run_job, payload, persist=True, owner_id=owner_id)
|
| 777 |
+
except BodyTooLarge as exc:
|
| 778 |
+
return JSONResponse(
|
| 779 |
+
{"state": "REJECTED", "error": str(exc), **ZERO_UPLIFT},
|
| 780 |
+
status_code=413,
|
| 781 |
+
)
|
| 782 |
+
except ContractError as exc:
|
| 783 |
+
return JSONResponse({"state": "REJECTED", "error": str(exc), **ZERO_UPLIFT}, status_code=422)
|
| 784 |
+
except Exception as exc:
|
| 785 |
+
return JSONResponse(
|
| 786 |
+
{"state": "UNAVAILABLE", "reason": type(exc).__name__, **ZERO_UPLIFT},
|
| 787 |
+
status_code=503,
|
| 788 |
+
)
|
| 789 |
+
status = 503 if record["result"]["state"] == "UNAVAILABLE" else 200
|
| 790 |
+
return JSONResponse(record, status_code=status)
|
| 791 |
+
|
| 792 |
+
@app.get(f"{prefix}/jobs/{{job_id}}")
|
| 793 |
+
async def compute_job(request: Request, job_id: str) -> JSONResponse:
|
| 794 |
+
try:
|
| 795 |
+
owner_id = _authorize_request(request)
|
| 796 |
+
except AuthenticationError as exc:
|
| 797 |
+
status = 503 if "not configured" in str(exc) else 401
|
| 798 |
+
return JSONResponse(
|
| 799 |
+
{"state": "UNAVAILABLE" if status == 503 else "UNAUTHORIZED",
|
| 800 |
+
"error": str(exc), **ZERO_UPLIFT},
|
| 801 |
+
status_code=status,
|
| 802 |
+
)
|
| 803 |
+
try:
|
| 804 |
+
record = get_job(job_id, owner_id=owner_id)
|
| 805 |
+
except ContractError as exc:
|
| 806 |
+
return JSONResponse({"state": "REJECTED", "error": str(exc), **ZERO_UPLIFT}, status_code=422)
|
| 807 |
+
if record is None:
|
| 808 |
+
return JSONResponse({"state": "NOT_FOUND", "job_id": job_id, **ZERO_UPLIFT}, status_code=404)
|
| 809 |
+
return JSONResponse(record)
|
| 810 |
+
|
| 811 |
+
@app.get(f"{prefix}/receipts/{{job_id}}")
|
| 812 |
+
async def compute_receipt(request: Request, job_id: str) -> JSONResponse:
|
| 813 |
+
try:
|
| 814 |
+
owner_id = _authorize_request(request)
|
| 815 |
+
except AuthenticationError as exc:
|
| 816 |
+
status = 503 if "not configured" in str(exc) else 401
|
| 817 |
+
return JSONResponse(
|
| 818 |
+
{"state": "UNAVAILABLE" if status == 503 else "UNAUTHORIZED",
|
| 819 |
+
"error": str(exc), **ZERO_UPLIFT},
|
| 820 |
+
status_code=status,
|
| 821 |
+
)
|
| 822 |
+
try:
|
| 823 |
+
record = get_job(job_id, owner_id=owner_id)
|
| 824 |
+
except ContractError as exc:
|
| 825 |
+
return JSONResponse({"state": "REJECTED", "error": str(exc), **ZERO_UPLIFT}, status_code=422)
|
| 826 |
+
if record is None:
|
| 827 |
+
return JSONResponse({"state": "NOT_FOUND", "job_id": job_id, **ZERO_UPLIFT}, status_code=404)
|
| 828 |
+
return JSONResponse(
|
| 829 |
+
{
|
| 830 |
+
"job_id": job_id,
|
| 831 |
+
"receipt": record["receipt"],
|
| 832 |
+
"dsse": record["dsse"],
|
| 833 |
+
"dsse_verification": record["dsse_verification"],
|
| 834 |
+
"lake": record["lake"],
|
| 835 |
+
}
|
| 836 |
+
)
|
| 837 |
+
|
| 838 |
+
@app.post(f"{prefix}/receipts/verify")
|
| 839 |
+
async def compute_verify(request: Request) -> JSONResponse:
|
| 840 |
+
try:
|
| 841 |
+
verdict = verify_job_record(await _bounded_body(request))
|
| 842 |
+
except ContractError as exc:
|
| 843 |
+
return JSONResponse({"valid": False, "error": str(exc), **ZERO_UPLIFT}, status_code=422)
|
| 844 |
+
return JSONResponse(verdict, status_code=200 if verdict["valid"] else 409)
|
| 845 |
+
|
| 846 |
+
return {
|
| 847 |
+
"registered": True,
|
| 848 |
+
"routes": [
|
| 849 |
+
f"{prefix}/capabilities",
|
| 850 |
+
f"{prefix}/jobs",
|
| 851 |
+
f"{prefix}/jobs/{{job_id}}",
|
| 852 |
+
f"{prefix}/receipts/{{job_id}}",
|
| 853 |
+
f"{prefix}/receipts/verify",
|
| 854 |
+
],
|
| 855 |
+
"operation_count": len(OPERATIONS),
|
| 856 |
+
"stateful_routes_require_auth": True,
|
| 857 |
+
"auth_secret": "A11OY_COMPUTE_TOKEN_SHA256",
|
| 858 |
+
**ZERO_UPLIFT,
|
| 859 |
+
}
|
| 860 |
+
|
| 861 |
+
|
| 862 |
+
__all__ = [
|
| 863 |
+
"ContractError",
|
| 864 |
+
"JOB_SCHEMA",
|
| 865 |
+
"OPERATIONS",
|
| 866 |
+
"RECEIPT_SCHEMA",
|
| 867 |
+
"RESULT_SCHEMA",
|
| 868 |
+
"capabilities",
|
| 869 |
+
"digest_json",
|
| 870 |
+
"get_job",
|
| 871 |
+
"parse_job",
|
| 872 |
+
"register",
|
| 873 |
+
"run_job",
|
| 874 |
+
"verify_job_record",
|
| 875 |
+
]
|
|
@@ -638,16 +638,16 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 638 |
n_before = len(app.router.routes)
|
| 639 |
|
| 640 |
@app.get(f"/api/{ns}/v1/yupay/doctrine", include_in_schema=False)
|
| 641 |
-
async def _doctrine()
|
| 642 |
return JSONResponse(doctrine())
|
| 643 |
|
| 644 |
@app.get(f"/api/{ns}/v1/yupay/demo", include_in_schema=False)
|
| 645 |
-
async def _demo(req: Request)
|
| 646 |
q = req.query_params.get("task")
|
| 647 |
return JSONResponse(demo(task_prompt=q))
|
| 648 |
|
| 649 |
@app.post(f"/api/{ns}/v1/yupay/compare", include_in_schema=False)
|
| 650 |
-
async def _compare(req: Request)
|
| 651 |
try:
|
| 652 |
body = await req.json()
|
| 653 |
except Exception:
|
|
@@ -659,7 +659,7 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 659 |
return JSONResponse(governed_compare(task=t, data_label="MODELED"))
|
| 660 |
|
| 661 |
@app.get(f"/api/{ns}/v1/yupay/receipts", include_in_schema=False)
|
| 662 |
-
async def _receipts()
|
| 663 |
tail = _RECEIPTS[-20:]
|
| 664 |
return JSONResponse({"count": len(_RECEIPTS),
|
| 665 |
"receipts": [{"payload": r["payload"],
|
|
@@ -667,7 +667,7 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 667 |
for r in tail]})
|
| 668 |
|
| 669 |
@app.post(f"/api/{ns}/v1/yupay/verify", include_in_schema=False)
|
| 670 |
-
async def _verify(req: Request)
|
| 671 |
try:
|
| 672 |
body = await req.json()
|
| 673 |
except Exception:
|
|
@@ -676,7 +676,7 @@ def register(app, ns: str = "a11oy") -> Dict[str, Any]:
|
|
| 676 |
return JSONResponse(verify_receipt(env))
|
| 677 |
|
| 678 |
@app.get("/yupay", include_in_schema=False)
|
| 679 |
-
async def _page()
|
| 680 |
return HTMLResponse(_PAGE_HTML.replace("{NS}", ns))
|
| 681 |
|
| 682 |
# Move the YUPAY routes just appended (the tail beyond n_before) to the FRONT,
|
|
|
|
| 638 |
n_before = len(app.router.routes)
|
| 639 |
|
| 640 |
@app.get(f"/api/{ns}/v1/yupay/doctrine", include_in_schema=False)
|
| 641 |
+
async def _doctrine(): # noqa: ANN202
|
| 642 |
return JSONResponse(doctrine())
|
| 643 |
|
| 644 |
@app.get(f"/api/{ns}/v1/yupay/demo", include_in_schema=False)
|
| 645 |
+
async def _demo(req: Request): # noqa: ANN202
|
| 646 |
q = req.query_params.get("task")
|
| 647 |
return JSONResponse(demo(task_prompt=q))
|
| 648 |
|
| 649 |
@app.post(f"/api/{ns}/v1/yupay/compare", include_in_schema=False)
|
| 650 |
+
async def _compare(req: Request): # noqa: ANN202
|
| 651 |
try:
|
| 652 |
body = await req.json()
|
| 653 |
except Exception:
|
|
|
|
| 659 |
return JSONResponse(governed_compare(task=t, data_label="MODELED"))
|
| 660 |
|
| 661 |
@app.get(f"/api/{ns}/v1/yupay/receipts", include_in_schema=False)
|
| 662 |
+
async def _receipts(): # noqa: ANN202
|
| 663 |
tail = _RECEIPTS[-20:]
|
| 664 |
return JSONResponse({"count": len(_RECEIPTS),
|
| 665 |
"receipts": [{"payload": r["payload"],
|
|
|
|
| 667 |
for r in tail]})
|
| 668 |
|
| 669 |
@app.post(f"/api/{ns}/v1/yupay/verify", include_in_schema=False)
|
| 670 |
+
async def _verify(req: Request): # noqa: ANN202
|
| 671 |
try:
|
| 672 |
body = await req.json()
|
| 673 |
except Exception:
|
|
|
|
| 676 |
return JSONResponse(verify_receipt(env))
|
| 677 |
|
| 678 |
@app.get("/yupay", include_in_schema=False)
|
| 679 |
+
async def _page(): # noqa: ANN202
|
| 680 |
return HTMLResponse(_PAGE_HTML.replace("{NS}", ns))
|
| 681 |
|
| 682 |
# Move the YUPAY routes just appended (the tail beyond n_before) to the FRONT,
|