diff --git a/src/crisisguard/__init__.py b/src/crisisguard/__init__.py index 699808a..3ded657 100644 --- a/src/crisisguard/__init__.py +++ b/src/crisisguard/__init__.py @@ -1,5 +1,6 @@ from .core import LocalPlan, SharedSignals, PlanDelta, GovernanceLog from .registry import GraphOfContracts +from .interop import to_canonical_ir __all__ = [ "LocalPlan", @@ -7,4 +8,5 @@ __all__ = [ "PlanDelta", "GovernanceLog", "GraphOfContracts", + "to_canonical_ir", ] diff --git a/src/crisisguard/interop.py b/src/crisisguard/interop.py new file mode 100644 index 0000000..8ecea0f --- /dev/null +++ b/src/crisisguard/interop.py @@ -0,0 +1,42 @@ +"""Interoperability helpers for CrisisGuard canonical IR. + +This module provides a tiny, well-scoped bridge that maps CrisisGuard +primitives (LocalPlan, PlanDelta, SharedSignals) into a lightweight +Interoperability Representation (IR). The IR is designed to be simple, +deterministic, and suitable for offline or cross-domain adapters that need +to interoperate without requiring a full networked graph of contracts. + +The function `to_canonical_ir` returns a dictionary with two sections: +- Objects: canonical representation of a LocalPlan +- Morphisms: a list of relevant delta and signal morphisms, when provided +""" + +from __future__ import annotations + +from crisisguard.core import LocalPlan, PlanDelta, SharedSignals + + +def to_canonical_ir(plan: LocalPlan, delta: PlanDelta | None = None, signals: SharedSignals | None = None) -> dict: + """Convert CrisisGuard primitives to a canonical IR dictionary. + + - plan is always represented under Objects.LocalPlan + - delta (if provided) is appended under Morphisms as PlanDelta payload + - signals (if provided) is appended under Morphisms as SharedSignals payload + The structure is intentionally minimal to ease cross-domain adapters and + offline reconciliation. + """ + + ir: dict = { + "Objects": { + "LocalPlan": plan.to_dict(), + }, + "Morphisms": [], + } + + if delta is not None: + ir["Morphisms"].append({"PlanDelta": delta.to_dict()}) + + if signals is not None: + ir["Morphisms"].append({"SharedSignals": signals.to_dict()}) + + return ir