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)