surrogate v1: REAL trained BLOCK/ALLOW HistGB (fidelity 0.9977 MEASURED) + receipt + scripts + honest card/provenance
Browse files- MODEL_PROVENANCE.json +19 -3
- README.md +39 -1
- TRAINING_RECEIPT.json +67 -0
- model.joblib +3 -0
- scripts/eval.py +24 -0
- scripts/forge.py +171 -0
MODEL_PROVENANCE.json
CHANGED
|
@@ -5,7 +5,23 @@
|
|
| 5 |
"id": "SZLHOLDINGS/szl-blocked",
|
| 6 |
"repository_type": "model",
|
| 7 |
"artifact_kind": "kernel-code-and-configuration",
|
| 8 |
-
"trained_weights_present":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
},
|
| 10 |
"source_of_record": {
|
| 11 |
"state": "VERIFIED_HF_SOURCE_OF_RECORD",
|
|
@@ -31,7 +47,7 @@
|
|
| 31 |
"claims": {
|
| 32 |
"github_repository_parity": "NOT_CLAIMED",
|
| 33 |
"reproducible_build": "NOT_CLAIMED",
|
| 34 |
-
"trained_model": "
|
| 35 |
"serving_process_revision": "NOT_APPLICABLE_REPOSITORY_ARTIFACT"
|
| 36 |
},
|
| 37 |
"limits": [
|
|
@@ -39,4 +55,4 @@
|
|
| 39 |
"The attestation overlay cannot self-embed its resulting Hub commit, so the immutable artifact_base_revision is the measured pre-overlay base.",
|
| 40 |
"No .bin, .safetensors, .pt, .pth, .onnx, or .gguf weight artifact was present in the measured base tree."
|
| 41 |
]
|
| 42 |
-
}
|
|
|
|
| 5 |
"id": "SZLHOLDINGS/szl-blocked",
|
| 6 |
"repository_type": "model",
|
| 7 |
"artifact_kind": "kernel-code-and-configuration",
|
| 8 |
+
"trained_weights_present": true,
|
| 9 |
+
"surrogate": {
|
| 10 |
+
"file": "model.joblib",
|
| 11 |
+
"sha256": "15f0537cd323aff977ff3d5abec065f1144693fe0ab99d5cbd0961fe3b8e7610",
|
| 12 |
+
"role": "BLOCK/ALLOW decision triage only \u2014 kernel policy chain remains sole ground truth",
|
| 13 |
+
"fidelity_MEASURED": {
|
| 14 |
+
"fidelity_vs_kernel_heldout": 0.9977,
|
| 15 |
+
"per_class_recall": {
|
| 16 |
+
"ALLOW": 0.9963,
|
| 17 |
+
"BLOCK_HARD": 1.0,
|
| 18 |
+
"BLOCK_ADVISORY": 0.9846
|
| 19 |
+
}
|
| 20 |
+
},
|
| 21 |
+
"receipt": "TRAINING_RECEIPT.json",
|
| 22 |
+
"reverify": "python scripts/eval.py"
|
| 23 |
+
},
|
| 24 |
+
"stdlib_only_note": "kernel package itself stays stdlib-only; the OPTIONAL surrogate needs sklearn+joblib"
|
| 25 |
},
|
| 26 |
"source_of_record": {
|
| 27 |
"state": "VERIFIED_HF_SOURCE_OF_RECORD",
|
|
|
|
| 47 |
"claims": {
|
| 48 |
"github_repository_parity": "NOT_CLAIMED",
|
| 49 |
"reproducible_build": "NOT_CLAIMED",
|
| 50 |
+
"trained_model": "SURROGATE_PRESENT_MEASURED_FIDELITY",
|
| 51 |
"serving_process_revision": "NOT_APPLICABLE_REPOSITORY_ARTIFACT"
|
| 52 |
},
|
| 53 |
"limits": [
|
|
|
|
| 55 |
"The attestation overlay cannot self-embed its resulting Hub commit, so the immutable artifact_base_revision is the measured pre-overlay base.",
|
| 56 |
"No .bin, .safetensors, .pt, .pth, .onnx, or .gguf weight artifact was present in the measured base tree."
|
| 57 |
]
|
| 58 |
+
}
|
README.md
CHANGED
|
@@ -5,8 +5,12 @@ tags:
|
|
| 5 |
- compliance
|
| 6 |
- annex-iv
|
| 7 |
- governance
|
|
|
|
|
|
|
|
|
|
| 8 |
- doi:10.5281/zenodo.19944926
|
| 9 |
library_name: kernels
|
|
|
|
| 10 |
license: apache-2.0
|
| 11 |
szl-governance:
|
| 12 |
verdict: HONEST-BLOCKED
|
|
@@ -28,7 +32,7 @@ szl-governance:
|
|
| 28 |
|
| 29 |
</div>
|
| 30 |
|
| 31 |
-
> **
|
| 32 |
|
| 33 |
**A refusal-first governed kernel.** When a governed call is denied, the op **never runs**, and the chain records an honest `BLOCKED` receipt rather than a success. Its companion `szl_euaiact` derives an **EU AI Act Annex IV-style draft technical-documentation skeleton** from that provenance — an organizational aid, not compliance evidence, legal advice, or a declaration of conformity.
|
| 34 |
|
|
@@ -79,6 +83,40 @@ Part of the [`szl-kernels`](https://huggingface.co/SZLHOLDINGS/szl-kernels) suit
|
|
| 79 |
|
| 80 |
Apache-2.0 · © 2026 SZL Holdings · Stephen P. Lutar · ORCID [0009-0001-0110-4173](https://orcid.org/0009-0001-0110-4173). Concept DOI [10.5281/zenodo.19944926](https://doi.org/10.5281/zenodo.19944926).
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
---
|
| 83 |
|
| 84 |
<sub><b>SZL Holdings honesty footer.</b> Λ = Conjecture 1 (advisory, never a theorem). locked-proven = exactly 8 {F1,F4,F7,F11,F12,F18,F19,F22}. Honesty labels: MEASURED / REPORTED / MODELED / HEURISTIC / UNKNOWN / UNAVAILABLE. Trust never 100% (ceiling 0.97). honest-BLOCKED is never flipped. <a href="https://a-11-oy.com">a-11-oy.com</a> · <a href="https://huggingface.co/SZLHOLDINGS">huggingface.co/SZLHOLDINGS</a></sub>
|
|
|
|
| 5 |
- compliance
|
| 6 |
- annex-iv
|
| 7 |
- governance
|
| 8 |
+
- sklearn
|
| 9 |
+
- surrogate
|
| 10 |
+
- tabular-classification
|
| 11 |
- doi:10.5281/zenodo.19944926
|
| 12 |
library_name: kernels
|
| 13 |
+
pipeline_tag: tabular-classification
|
| 14 |
license: apache-2.0
|
| 15 |
szl-governance:
|
| 16 |
verdict: HONEST-BLOCKED
|
|
|
|
| 32 |
|
| 33 |
</div>
|
| 34 |
|
| 35 |
+
> **🟩 Kernel + REAL trained surrogate.** The governance kernel (pure-Python, stdlib-only) is UNCHANGED and remains the sole ground truth. Since **surrogate v1** this repo also ships `model.joblib` — a real trained sklearn classifier that triages the BLOCK/ALLOW verdict `GovernedGate.decide(...)` would return, with **MEASURED** fidelity **0.9977** (agreement vs the kernel on a held-out split). The surrogate is a fast pre-gate; the kernel's honest-BLOCKED policy chain stays authoritative and `get_kernel`-discoverable. No verdict is ever coerced. **Λ is not touched here and stays Conjecture 1 (open).**
|
| 36 |
|
| 37 |
**A refusal-first governed kernel.** When a governed call is denied, the op **never runs**, and the chain records an honest `BLOCKED` receipt rather than a success. Its companion `szl_euaiact` derives an **EU AI Act Annex IV-style draft technical-documentation skeleton** from that provenance — an organizational aid, not compliance evidence, legal advice, or a declaration of conformity.
|
| 38 |
|
|
|
|
| 83 |
|
| 84 |
Apache-2.0 · © 2026 SZL Holdings · Stephen P. Lutar · ORCID [0009-0001-0110-4173](https://orcid.org/0009-0001-0110-4173). Concept DOI [10.5281/zenodo.19944926](https://doi.org/10.5281/zenodo.19944926).
|
| 85 |
|
| 86 |
+
## Trained BLOCK/ALLOW surrogate v1 (MEASURED — see `TRAINING_RECEIPT.json`)
|
| 87 |
+
|
| 88 |
+
A real sklearn `HistGradientBoostingClassifier` trained on **24,000 governed requests**
|
| 89 |
+
synthesized and **labeled by this kernel itself** (`GovernedGate.decide`, seed 20260721;
|
| 90 |
+
600 samples re-audited by independent full kernel replay during generation — all agreed).
|
| 91 |
+
Features are structural observables of the request (capabilities, action, hard flag) plus
|
| 92 |
+
the advisory Λ axes — the surrogate never runs the policy chain or signs a receipt.
|
| 93 |
+
|
| 94 |
+
| metric | value |
|
| 95 |
+
|---|---|
|
| 96 |
+
| fidelity vs kernel (held-out agreement) | **0.9977** |
|
| 97 |
+
| test accuracy (3 classes) | **0.9977** |
|
| 98 |
+
|
| 99 |
+
| per-class recall | value |
|
| 100 |
+
|---|---|
|
| 101 |
+
| `ALLOW` | 0.9963 |
|
| 102 |
+
| `BLOCK_HARD` (hard security deny dominates) | 1.0000 |
|
| 103 |
+
| `BLOCK_ADVISORY` (advisory Λ tightened ALLOW→BLOCK) | 0.9846 |
|
| 104 |
+
|
| 105 |
+
**Honest blind spot / boundary:** the surrogate predicts the *decision*, never the *receipt*.
|
| 106 |
+
It cannot emit the tamper-evident SHA3-256 chain receipt and must never be used to flip a
|
| 107 |
+
BLOCK to ALLOW — the deny-by-default kernel policy remains the authority. Class balance is
|
| 108 |
+
kernel-driven (`BLOCK_HARD` dominates because deny-by-default is the safe ground state):
|
| 109 |
+
counts ALLOW=2713, BLOCK_HARD=18357, BLOCK_ADVISORY=2930.
|
| 110 |
+
Λ untouched = Conjecture 1.
|
| 111 |
+
|
| 112 |
+
```python
|
| 113 |
+
import joblib
|
| 114 |
+
clf = joblib.load("model.joblib") # feature spec: TRAINING_RECEIPT.json data.features
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
Re-verify everything: `python scripts/eval.py` (sha256-checks the shipped model against the
|
| 118 |
+
receipt, regenerates the seeded kernel-labeled dataset, retrains, and compares fidelity within ±0.02).
|
| 119 |
+
|
| 120 |
---
|
| 121 |
|
| 122 |
<sub><b>SZL Holdings honesty footer.</b> Λ = Conjecture 1 (advisory, never a theorem). locked-proven = exactly 8 {F1,F4,F7,F11,F12,F18,F19,F22}. Honesty labels: MEASURED / REPORTED / MODELED / HEURISTIC / UNKNOWN / UNAVAILABLE. Trust never 100% (ceiling 0.97). honest-BLOCKED is never flipped. <a href="https://a-11-oy.com">a-11-oy.com</a> · <a href="https://huggingface.co/SZLHOLDINGS">huggingface.co/SZLHOLDINGS</a></sub>
|
TRAINING_RECEIPT.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"artifact": "SZLHOLDINGS/szl-blocked surrogate v1",
|
| 3 |
+
"role": "BLOCK/ALLOW decision triage surrogate \u2014 kernel remains ground truth",
|
| 4 |
+
"generator": {
|
| 5 |
+
"script": "scripts/forge.py",
|
| 6 |
+
"seed": 20260721,
|
| 7 |
+
"kernel_version": "0.1.0",
|
| 8 |
+
"kernel_labelled": true,
|
| 9 |
+
"kernel_audited_samples": 600,
|
| 10 |
+
"policy": "deny_by_default([allow_if_capability('run_norm'), deny_if_flag('exfiltration'), deny_if_action_in({'exfiltrate','delete_all','drop_table'})])",
|
| 11 |
+
"lambda_threshold": 0.5
|
| 12 |
+
},
|
| 13 |
+
"data": {
|
| 14 |
+
"rows": 24000,
|
| 15 |
+
"classes": [
|
| 16 |
+
"ALLOW",
|
| 17 |
+
"BLOCK_HARD",
|
| 18 |
+
"BLOCK_ADVISORY"
|
| 19 |
+
],
|
| 20 |
+
"class_counts": {
|
| 21 |
+
"ALLOW": 2713,
|
| 22 |
+
"BLOCK_HARD": 18357,
|
| 23 |
+
"BLOCK_ADVISORY": 2930
|
| 24 |
+
},
|
| 25 |
+
"split": "80/20 stratified",
|
| 26 |
+
"features": [
|
| 27 |
+
"has_required_capability",
|
| 28 |
+
"n_capabilities",
|
| 29 |
+
"action_blocklisted",
|
| 30 |
+
"hard_flag_set",
|
| 31 |
+
"advisory_axes_present",
|
| 32 |
+
"n_axes",
|
| 33 |
+
"axes_min",
|
| 34 |
+
"axes_mean",
|
| 35 |
+
"axes_any_zero"
|
| 36 |
+
],
|
| 37 |
+
"feature_policy": "structural observables of the request + advisory \u039b axes only; the surrogate never signs receipts or replaces the policy chain"
|
| 38 |
+
},
|
| 39 |
+
"model": {
|
| 40 |
+
"type": "sklearn.HistGradientBoostingClassifier",
|
| 41 |
+
"params": {
|
| 42 |
+
"max_iter": 300,
|
| 43 |
+
"early_stopping": true,
|
| 44 |
+
"random_state": 20260721
|
| 45 |
+
},
|
| 46 |
+
"file": "model.joblib",
|
| 47 |
+
"sha256": "15f0537cd323aff977ff3d5abec065f1144693fe0ab99d5cbd0961fe3b8e7610"
|
| 48 |
+
},
|
| 49 |
+
"metrics_MEASURED": {
|
| 50 |
+
"fidelity_vs_kernel_heldout": 0.9977,
|
| 51 |
+
"test_accuracy": 0.9977,
|
| 52 |
+
"per_class_recall": {
|
| 53 |
+
"ALLOW": 0.9963,
|
| 54 |
+
"BLOCK_HARD": 1.0,
|
| 55 |
+
"BLOCK_ADVISORY": 0.9846
|
| 56 |
+
}
|
| 57 |
+
},
|
| 58 |
+
"environment": {
|
| 59 |
+
"python": "3.12.12",
|
| 60 |
+
"sklearn": "1.9.0",
|
| 61 |
+
"numpy": "2.5.1",
|
| 62 |
+
"host": "replit 2-vCPU container",
|
| 63 |
+
"wall_seconds": 1.0
|
| 64 |
+
},
|
| 65 |
+
"honesty": "Every number above is MEASURED by this run. Fidelity = agreement%% with GovernedGate.decide on a held-out split. The surrogate is a fast pre-gate; the kernel's honest-BLOCKED policy chain stays authoritative. \u039b untouched = Conjecture 1.",
|
| 66 |
+
"trained_at_utc": "2026-07-21T02:49:46Z"
|
| 67 |
+
}
|
model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:15f0537cd323aff977ff3d5abec065f1144693fe0ab99d5cbd0961fe3b8e7610
|
| 3 |
+
size 448832
|
scripts/eval.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Re-verify the surrogate: sha256 the shipped model against TRAINING_RECEIPT.json,
|
| 3 |
+
then deterministically regenerate the seeded dataset via scripts/forge.py and
|
| 4 |
+
compare re-measured fidelity to the receipt (tolerance 0.02 across lib versions).
|
| 5 |
+
Run from repo root: python scripts/eval.py"""
|
| 6 |
+
import hashlib, json, subprocess, sys, tempfile, os, shutil
|
| 7 |
+
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 8 |
+
receipt = json.load(open(f"{root}/TRAINING_RECEIPT.json"))
|
| 9 |
+
got = hashlib.sha256(open(f"{root}/model.joblib", "rb").read()).hexdigest()
|
| 10 |
+
want = receipt["model"]["sha256"]
|
| 11 |
+
print(f"model.joblib sha256 {'MATCHES receipt' if got==want else 'MISMATCH — refuse'}: {got[:16]}…")
|
| 12 |
+
if got != want:
|
| 13 |
+
sys.exit(1)
|
| 14 |
+
with tempfile.TemporaryDirectory() as td:
|
| 15 |
+
shutil.copy(f"{root}/scripts/forge.py", f"{td}/forge.py")
|
| 16 |
+
out = subprocess.run([sys.executable, f"{td}/forge.py"], capture_output=True, text=True, cwd=td)
|
| 17 |
+
print(out.stdout[-400:] if out.returncode == 0 else out.stderr[-600:])
|
| 18 |
+
if out.returncode:
|
| 19 |
+
sys.exit(1)
|
| 20 |
+
re_receipt = json.load(open(f"{td}/TRAINING_RECEIPT.json"))
|
| 21 |
+
d = abs(re_receipt["metrics_MEASURED"]["fidelity_vs_kernel_heldout"]
|
| 22 |
+
- receipt["metrics_MEASURED"]["fidelity_vs_kernel_heldout"])
|
| 23 |
+
print(f"re-measured fidelity delta vs receipt: {d:.4f} ({'OK ≤0.02' if d<=0.02 else 'FAIL'})")
|
| 24 |
+
sys.exit(0 if d <= 0.02 else 1)
|
scripts/forge.py
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Forge a REAL trained surrogate for szl-blocked.
|
| 3 |
+
Kernel = ground truth. Surrogate = fast BLOCK/ALLOW triage: given a governed
|
| 4 |
+
request's structural observables (capabilities, action, flags) plus the advisory
|
| 5 |
+
Λ axes, predict what GovernedGate.decide(...) would return — ALLOW, BLOCK by
|
| 6 |
+
HARD security, or BLOCK by advisory Λ. The kernel's deny-by-default policy and
|
| 7 |
+
non-compensatory Λ gate are the sole labeler; a sample of labels is re-audited
|
| 8 |
+
by full kernel replay and MUST agree or the run fails loudly.
|
| 9 |
+
Seeded, receipted, reproducible."""
|
| 10 |
+
import json, os, random, sys, time, hashlib, platform
|
| 11 |
+
_here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 12 |
+
if os.path.isdir(os.path.join(_here, "build", "torch-universal")):
|
| 13 |
+
sys.path.insert(0, os.path.join(_here, "build", "torch-universal")) # in-repo run
|
| 14 |
+
else:
|
| 15 |
+
sys.path.insert(0, "/tmp/kernel-probe/szl-blocked/build/torch-universal") # forge-dev run
|
| 16 |
+
import szl_blocked as sb
|
| 17 |
+
import numpy as np
|
| 18 |
+
from sklearn.ensemble import HistGradientBoostingClassifier
|
| 19 |
+
from sklearn.model_selection import train_test_split
|
| 20 |
+
from sklearn.metrics import accuracy_score, recall_score
|
| 21 |
+
import joblib
|
| 22 |
+
|
| 23 |
+
SEED = 20260721
|
| 24 |
+
random.seed(SEED); np.random.seed(SEED)
|
| 25 |
+
T0 = time.time()
|
| 26 |
+
|
| 27 |
+
# The universe the surrogate learns over. These mirror the kernel's own rules:
|
| 28 |
+
# allow_if_capability("run_norm") -> needs capability present
|
| 29 |
+
# deny_if_action_in({"exfiltrate","delete_all","drop_table"}) -> hard blocklist
|
| 30 |
+
# deny_if_flag("exfiltration") -> hard flag deny
|
| 31 |
+
CAPS_UNIVERSE = ["run_norm", "read_public", "write_logs", "call_model"]
|
| 32 |
+
REQUIRED_CAP = "run_norm"
|
| 33 |
+
BLOCKLIST = {"exfiltrate", "delete_all", "drop_table"}
|
| 34 |
+
ACTIONS = ["summarize", "rms_norm", "classify", "embed",
|
| 35 |
+
"exfiltrate", "delete_all", "drop_table"]
|
| 36 |
+
HARD_FLAG = "exfiltration"
|
| 37 |
+
LAMBDA_THRESHOLD = 0.5
|
| 38 |
+
|
| 39 |
+
CLASSES = ["ALLOW", "BLOCK_HARD", "BLOCK_ADVISORY"]
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def build_policy():
|
| 43 |
+
"""The fixed hard policy the surrogate is trained against (deny-by-default)."""
|
| 44 |
+
return sb.deny_by_default([
|
| 45 |
+
sb.allow_if_capability(REQUIRED_CAP),
|
| 46 |
+
sb.deny_if_flag(HARD_FLAG),
|
| 47 |
+
sb.deny_if_action_in(BLOCKLIST),
|
| 48 |
+
])
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def synth_request():
|
| 52 |
+
"""Synthesize a governed request + advisory axes across the decision space."""
|
| 53 |
+
caps = [c for c in CAPS_UNIVERSE if random.random() < 0.5]
|
| 54 |
+
action = random.choice(ACTIONS)
|
| 55 |
+
flag = 1 if random.random() < 0.18 else 0
|
| 56 |
+
req = {"capabilities": caps, "action": action}
|
| 57 |
+
if flag:
|
| 58 |
+
req[HARD_FLAG] = True
|
| 59 |
+
# advisory Λ axes: sometimes absent (abstain), sometimes present with a
|
| 60 |
+
# spread that straddles the threshold; occasionally a zero-route axis.
|
| 61 |
+
if random.random() < 0.25:
|
| 62 |
+
axes = None
|
| 63 |
+
else:
|
| 64 |
+
k = random.randint(2, 4)
|
| 65 |
+
axes = [round(random.uniform(0.0, 1.0), 4) for _ in range(k)]
|
| 66 |
+
if random.random() < 0.12:
|
| 67 |
+
axes[random.randrange(k)] = 0.0 # non-compensatory zero-route
|
| 68 |
+
return req, axes
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def kernel_label(req, axes):
|
| 72 |
+
"""Ground truth: exactly what GovernedGate.decide returns, plus which
|
| 73 |
+
authority dominated (fresh chain per call — decision is chain-independent)."""
|
| 74 |
+
gate = sb.GovernedGate(policy=build_policy(), lambda_threshold=LAMBDA_THRESHOLD,
|
| 75 |
+
chain=sb.UnifiedReceiptChain())
|
| 76 |
+
d = gate.decide(request=req, gov_axes=axes)
|
| 77 |
+
if d.allowed:
|
| 78 |
+
return "ALLOW"
|
| 79 |
+
if d.dominant == sb.DOMINANT_HARD:
|
| 80 |
+
return "BLOCK_HARD"
|
| 81 |
+
return "BLOCK_ADVISORY"
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def features(req, axes):
|
| 85 |
+
"""Structural observables of the request + advisory axes. These are what a
|
| 86 |
+
fast pre-gate can see WITHOUT running the policy chain."""
|
| 87 |
+
caps = set(req.get("capabilities") or [])
|
| 88 |
+
action = req.get("action")
|
| 89 |
+
has_req_cap = int(REQUIRED_CAP in caps)
|
| 90 |
+
n_caps = len(caps)
|
| 91 |
+
action_blocklisted = int(action in BLOCKLIST)
|
| 92 |
+
flag_set = int(bool(req.get(HARD_FLAG)))
|
| 93 |
+
# advisory axes summary (non-compensatory: min matters most)
|
| 94 |
+
if axes is None:
|
| 95 |
+
axes_present = 0
|
| 96 |
+
k = 0
|
| 97 |
+
amin = -1.0
|
| 98 |
+
amean = -1.0
|
| 99 |
+
any_zero = 0
|
| 100 |
+
else:
|
| 101 |
+
axes_present = 1
|
| 102 |
+
k = len(axes)
|
| 103 |
+
amin = min(axes) if axes else -1.0
|
| 104 |
+
amean = sum(axes) / len(axes) if axes else -1.0
|
| 105 |
+
any_zero = int(any(a <= 0.0 for a in axes))
|
| 106 |
+
return [has_req_cap, n_caps, action_blocklisted, flag_set,
|
| 107 |
+
axes_present, k, amin, amean, any_zero]
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
FEATURE_NAMES = ["has_required_capability", "n_capabilities", "action_blocklisted",
|
| 111 |
+
"hard_flag_set", "advisory_axes_present", "n_axes",
|
| 112 |
+
"axes_min", "axes_mean", "axes_any_zero"]
|
| 113 |
+
|
| 114 |
+
# ---- generate ----
|
| 115 |
+
N = 24000
|
| 116 |
+
X, y = [], []
|
| 117 |
+
audit_idx = set(random.sample(range(N), 600))
|
| 118 |
+
audit_checked = 0
|
| 119 |
+
policy = build_policy()
|
| 120 |
+
for i in range(N):
|
| 121 |
+
req, axes = synth_request()
|
| 122 |
+
lbl = kernel_label(req, axes)
|
| 123 |
+
X.append(features(req, axes)); y.append(lbl)
|
| 124 |
+
# ground-truth audit: independent fresh kernel replay must agree
|
| 125 |
+
if i in audit_idx:
|
| 126 |
+
gate2 = sb.GovernedGate(policy=build_policy(), lambda_threshold=LAMBDA_THRESHOLD,
|
| 127 |
+
chain=sb.UnifiedReceiptChain())
|
| 128 |
+
d2 = gate2.decide(request=req, gov_axes=axes)
|
| 129 |
+
replay = ("ALLOW" if d2.allowed else
|
| 130 |
+
("BLOCK_HARD" if d2.dominant == sb.DOMINANT_HARD else "BLOCK_ADVISORY"))
|
| 131 |
+
assert replay == lbl, f"kernel disagrees on sample {i}: {replay} != {lbl} req={req} axes={axes}"
|
| 132 |
+
audit_checked += 1
|
| 133 |
+
|
| 134 |
+
X = np.array(X, dtype=np.float64); y = np.array(y)
|
| 135 |
+
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, random_state=SEED, stratify=y)
|
| 136 |
+
clf = HistGradientBoostingClassifier(random_state=SEED, max_iter=300, early_stopping=True)
|
| 137 |
+
clf.fit(Xtr, ytr)
|
| 138 |
+
pred = clf.predict(Xte)
|
| 139 |
+
acc = accuracy_score(yte, pred) # this IS the fidelity: agreement% vs kernel on held-out
|
| 140 |
+
per_class_recall = {c: float(recall_score(yte == c, pred == c, zero_division=0)) for c in CLASSES}
|
| 141 |
+
|
| 142 |
+
out = os.path.dirname(os.path.abspath(__file__))
|
| 143 |
+
joblib.dump(clf, f"{out}/model.joblib")
|
| 144 |
+
model_sha = hashlib.sha256(open(f"{out}/model.joblib", "rb").read()).hexdigest()
|
| 145 |
+
receipt = {
|
| 146 |
+
"artifact": "SZLHOLDINGS/szl-blocked surrogate v1",
|
| 147 |
+
"role": "BLOCK/ALLOW decision triage surrogate — kernel remains ground truth",
|
| 148 |
+
"generator": {"script": "scripts/forge.py", "seed": SEED, "kernel_version": sb.__version__,
|
| 149 |
+
"kernel_labelled": True, "kernel_audited_samples": audit_checked,
|
| 150 |
+
"policy": "deny_by_default([allow_if_capability('run_norm'), deny_if_flag('exfiltration'), deny_if_action_in({'exfiltrate','delete_all','drop_table'})])",
|
| 151 |
+
"lambda_threshold": LAMBDA_THRESHOLD},
|
| 152 |
+
"data": {"rows": int(len(y)), "classes": CLASSES,
|
| 153 |
+
"class_counts": {c: int((y == c).sum()) for c in CLASSES},
|
| 154 |
+
"split": "80/20 stratified", "features": FEATURE_NAMES,
|
| 155 |
+
"feature_policy": "structural observables of the request + advisory Λ axes only; the surrogate never signs receipts or replaces the policy chain"},
|
| 156 |
+
"model": {"type": "sklearn.HistGradientBoostingClassifier",
|
| 157 |
+
"params": {"max_iter": 300, "early_stopping": True, "random_state": SEED},
|
| 158 |
+
"file": "model.joblib", "sha256": model_sha},
|
| 159 |
+
"metrics_MEASURED": {"fidelity_vs_kernel_heldout": round(float(acc), 4),
|
| 160 |
+
"test_accuracy": round(float(acc), 4),
|
| 161 |
+
"per_class_recall": {k: round(v, 4) for k, v in per_class_recall.items()}},
|
| 162 |
+
"environment": {"python": platform.python_version(), "sklearn": __import__("sklearn").__version__,
|
| 163 |
+
"numpy": np.__version__, "host": "replit 2-vCPU container",
|
| 164 |
+
"wall_seconds": round(time.time() - T0, 1)},
|
| 165 |
+
"honesty": "Every number above is MEASURED by this run. Fidelity = agreement%% with GovernedGate.decide on a held-out split. The surrogate is a fast pre-gate; the kernel's honest-BLOCKED policy chain stays authoritative. Λ untouched = Conjecture 1.",
|
| 166 |
+
"trained_at_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
| 167 |
+
}
|
| 168 |
+
with open(f"{out}/TRAINING_RECEIPT.json", "w") as f:
|
| 169 |
+
json.dump(receipt, f, indent=2)
|
| 170 |
+
print(json.dumps(receipt["metrics_MEASURED"], indent=2))
|
| 171 |
+
print(f"rows={len(y)} kernel_audited_samples={audit_checked} wall={receipt['environment']['wall_seconds']}s")
|