bert-agent / agent /ere_gate.py
SNAPKITTYWEST's picture
push from SNAPKITTYWEST/bert-agent
30f011f verified
Raw
History Blame Contribute Delete
4.24 kB
"""
ERE gate adapter for the BERT entailment agent.
Wraps every /verify response through the five-gate ERE protocol before
the result is returned to the caller. A verdict that fails any gate is
suppressed β€” the caller receives an ERE_HALT response instead.
Gates (from sovereign-engine-v2/src/tools/ere.py):
P1 -- No secrets in the output payload
P2 -- No eval / code injection in the output
P3 -- Loop safety
P4 -- No telemetry beacons
P5 -- SHA-256 audit seal (only if P1-P4 pass)
The P5 seal is stored alongside the BLAKE3 attestation in the WORM ledger,
giving each verified claim two independent cryptographic commitments:
- BLAKE3 (daemon layer, over model + threshold + score + source)
- SHA-256 ERE seal (gate layer, over agent_id + intent + verdict JSON)
"""
from __future__ import annotations
import json
import sys
import os
# Allow running from the repo root without installing
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from dataclasses import dataclass
# Import ERE from sovereign-engine-v2 if available; else use bundled copy
try:
# If sovereign-engine-v2 is on the path
from src.tools.ere import EREGate, EREResult, ere_check # type: ignore
except ImportError:
# Bundled minimal implementation (identical logic)
from agent._ere_bundled import EREGate, EREResult, ere_check # type: ignore
@dataclass
class GatedVerdict:
"""Result returned by the ERE gate layer."""
allowed: bool # True iff all five gates passed
verdict: dict | None # Original verdict payload, or None if halted
ere_seal: str | None # P5 SHA-256 seal, or None if gates failed
gate_results: dict # P1..P5 gate verdicts
violations: list[str] # Human-readable violation descriptions
def to_dict(self) -> dict:
if self.allowed:
return {
**self.verdict,
"ere_seal": self.ere_seal,
"ere_gates": self.gate_results,
}
return {
"allowed": False,
"ere_halt": True,
"violations": self.violations,
"ere_gates": self.gate_results,
}
class BERTEREGate:
"""
Wraps a raw BERT /verify response through the ERE five-gate protocol.
Usage:
gate = BERTEREGate()
raw = {"score": 0.98, "verdict": "Entailment", "hash": "a3f8..."}
gated = gate.check(
premise="The Battle of Hastings took place in 1066.",
hypothesis="Hastings occurred in 1066.",
raw_verdict=raw,
)
if not gated.allowed:
raise RuntimeError(f"ERE halt: {gated.violations}")
return gated.to_dict()
"""
def __init__(self) -> None:
self._gate = EREGate()
def check(
self,
premise: str,
hypothesis: str,
raw_verdict: dict,
) -> GatedVerdict:
"""
Run ERE gates over the serialized verdict payload.
The output that ERE inspects is the JSON-serialized verdict β€” any
secrets, eval patterns, or telemetry injected by a compromised model
or adversarial input would appear here.
"""
output_str = json.dumps(raw_verdict, sort_keys=True)
intent = f"entailment:{premise[:80]}|{hypothesis[:80]}"
result: EREResult = self._gate.check(
agent_id="bert-entailment-agent",
intent=intent,
output=output_str,
)
return GatedVerdict(
allowed=result.passed,
verdict=raw_verdict if result.passed else None,
ere_seal=result.seal,
gate_results=result.gates,
violations=result.violations,
)
# ── Module-level singleton ────────────────────────────────────────────────────
_default = BERTEREGate()
def gate_verdict(premise: str, hypothesis: str, raw_verdict: dict) -> GatedVerdict:
"""Module-level convenience wrapper."""
return _default.check(premise, hypothesis, raw_verdict)