build(agent): jabba#56a767 iteration

This commit is contained in:
agent-56a7678c6cd71659 2026-04-29 20:46:59 +02:00
parent a443cdc797
commit 7dabb0a7f4
4 changed files with 98 additions and 1 deletions

View File

@ -6,7 +6,7 @@ and Safety/Privacy contracts, a shadow planner, a simple on-device safety proof
hook, and a tamper-evident governance ledger. hook, and a tamper-evident governance ledger.
""" """
from .dsl import LocalProblem, SafetyContracts, PrivacyContracts, PlanDelta from .dsl import LocalProblem, SafetyContracts, PrivacyContracts, PlanDelta, PoeticCert, ReplayBundle
from .planner import ShadowPlanner, PlanResult from .planner import ShadowPlanner, PlanResult
from .safety import verify_plan from .safety import verify_plan
from .governance import GovernanceLedger from .governance import GovernanceLedger
@ -16,6 +16,8 @@ __all__ = [
"SafetyContracts", "SafetyContracts",
"PrivacyContracts", "PrivacyContracts",
"PlanDelta", "PlanDelta",
"PoeticCert",
"ReplayBundle",
"ShadowPlanner", "ShadowPlanner",
"PlanResult", "PlanResult",
"verify_plan", "verify_plan",

View File

@ -47,3 +47,36 @@ class PlanDelta:
delta: Dict[str, Any] = field(default_factory=dict) delta: Dict[str, Any] = field(default_factory=dict)
version: int = 0 version: int = 0
metadata: Dict[str, Any] = field(default_factory=dict) metadata: Dict[str, Any] = field(default_factory=dict)
@dataclass
class PoeticCert:
"""Compact human+machine verifiable certificate for quick triage.
- invariants: key safety/resource invariants (collision, energy envelopes)
- summary: short natural-language summary for on-call triage
- issued_by: identifier of the issuer (device or service)
- timestamp: optional ISO timestamp string
"""
invariants: Dict[str, Any] = field(default_factory=dict)
summary: str = ""
issued_by: str = ""
timestamp: str = ""
@dataclass
class ReplayBundle:
"""Signed, Merkle-linked plan trace bundle used for deterministic replay.
- entries: list of logged entries (dicts)
- signer: identifier of signer
- merkle_root: compact hex digest representing the bundle contents
- nonce: optional replay nonce
"""
entries: List[Dict[str, Any]] = field(default_factory=list)
signer: str = ""
merkle_root: str = ""
nonce: str = ""

View File

@ -4,6 +4,10 @@ import hashlib
import json import json
from datetime import datetime from datetime import datetime
from typing import List from typing import List
from typing import Tuple
import json
from .dsl import PoeticCert, ReplayBundle
class GovernanceLedger: class GovernanceLedger:
@ -30,6 +34,41 @@ class GovernanceLedger:
self._head_hash = hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest() self._head_hash = hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()
self._entries.append(payload) self._entries.append(payload)
def emit_poetic_cert(self, invariants: dict, summary: str, issuer: str) -> PoeticCert:
"""Emit a compact PoeticCert for quick triage and machine checks.
This is intentionally minimal and human-readable while remaining
machine-checkable.
"""
timestamp = datetime.utcnow().isoformat() + "Z"
cert = PoeticCert(invariants=invariants, summary=summary, issued_by=issuer, timestamp=timestamp)
# Also log the issuance to the ledger for auditability
self.log({"type": "poetic_cert_issued", "cert_summary": summary, "issued_by": issuer})
return cert
def create_replay_bundle(self, entries: List[dict], signer: str, nonce: str = "") -> ReplayBundle:
"""Construct a ReplayBundle with a compact merkle-style root.
For the MVP we compute a deterministic root by hashing each entry and
then hashing the concatenation of sorted entry hashes. This produces a
compact fingerprint suitable for off-device anchoring.
"""
# Normalize and hash entries deterministically
entry_hashes = []
for e in entries:
h = hashlib.sha256(json.dumps(e, sort_keys=True).encode()).hexdigest()
entry_hashes.append(h)
# deterministic ordering
entry_hashes.sort()
concat = "".join(entry_hashes).encode()
merkle_root = hashlib.sha256(concat).hexdigest() if concat else ""
bundle = ReplayBundle(entries=list(entries), signer=signer, merkle_root=merkle_root, nonce=nonce)
# log bundle creation
self.log({"type": "replay_bundle_created", "signer": signer, "merkle_root": merkle_root})
return bundle
@property @property
def entries(self) -> List[dict]: def entries(self) -> List[dict]:
return self._entries[:] return self._entries[:]

View File

@ -0,0 +1,23 @@
from missionledger.governance import GovernanceLedger
def test_poetic_cert_and_replay_bundle_creation():
gl = GovernanceLedger(device_id="test-device-2")
invariants = {"collision_envelope": 1.2, "energy_budget": 42}
cert = gl.emit_poetic_cert(invariants=invariants, summary="Safe envelope OK", issuer="planner-v1")
assert cert.issued_by == "planner-v1"
assert "collision_envelope" in cert.invariants
entries = [
{"event": "plan_step", "step": 1},
{"event": "plan_step", "step": 2},
]
bundle = gl.create_replay_bundle(entries=entries, signer="device-A", nonce="n-123")
assert bundle.signer == "device-A"
assert bundle.merkle_root != ""
assert len(bundle.entries) == 2
# ensure ledger recorded the bundle creation as an entry
assert any(e.get("entry", {}).get("type") == "replay_bundle_created" for e in gl.entries)