idea155-hopemesh-2-0/hopemesh/sdk.py

85 lines
2.8 KiB
Python

from __future__ import annotations
"""Tiny DSL-like helpers for HopeMesh primitives and contract tooling."""
from typing import Iterable
from .core import LocalProblem, SharedVariables, PlanDelta, Policy, AttestationHint, AuditLog, PrivacyBudget
from .contracts import validate_plan_deltas
def make_local_problem(
name: str,
region: str | None = None,
objective: str = "",
constraints: dict | None = None,
**metadata,
) -> LocalProblem:
return LocalProblem(name=name, region=region, objective=objective, constraints=constraints or {}, metadata=metadata)
def make_shared_variables(
description: str = "",
data: dict | None = None,
aggregate_type: str = "sum",
privacy_budget_tag: str | None = None,
source_regions: list[str] | None = None,
) -> SharedVariables:
return SharedVariables(
description=description,
data=data or {},
aggregate_type=aggregate_type,
privacy_budget_tag=privacy_budget_tag,
source_regions=source_regions or [],
)
def make_plan_delta(
delta_id: str,
actions: list[dict],
actor_did: str | None = None,
causality: dict | None = None,
policy_tags: list[str] | None = None,
privacy_budget_tag: str | None = None,
signature: str | None = None,
**annotations,
) -> PlanDelta:
return PlanDelta(
delta_id=delta_id,
actions=actions,
actor_did=actor_did,
causality=causality or {},
policy_tags=policy_tags or [],
privacy_budget_tag=privacy_budget_tag,
signature=signature,
annotations=annotations,
)
def make_policy(policy_id: str, **rules) -> Policy:
return Policy(policy_id=policy_id, rules=rules)
def make_attestation_hint(hint_id: str, scheme: str = "dummy", payload: dict | None = None) -> AttestationHint:
return AttestationHint(hint_id=hint_id, scheme=scheme, payload=payload or {})
def make_audit_log(entry_id: str, message: str, signature: str | None = None) -> AuditLog:
return AuditLog(entry_id=entry_id, message=message, signature=signature)
def make_privacy_budget(budget_id: str, limit: float) -> PrivacyBudget:
return PrivacyBudget(budget_id=budget_id, limit=limit)
def merge_plan_deltas(deltas: Iterable[PlanDelta]) -> PlanDelta:
ordered = sorted(deltas, key=lambda delta: (delta.timestamp, delta.delta_id))
actions: list[dict] = []
contributors: list[str] = []
for delta in ordered:
contributors.append(delta.delta_id)
actions.extend(delta.actions)
delta_id = "merged-" + "-".join(contributors) if contributors else "merged-empty"
return PlanDelta(
delta_id=delta_id,
actions=actions,
causality={"merged_from": len(contributors)},
annotations={"contributors": contributors},
)
def validate_deltas(deltas: Iterable[PlanDelta]) -> list[str]:
return validate_plan_deltas(deltas)