From a4b81b2b9f546cb097f872e42700817fb623c201 Mon Sep 17 00:00:00 2001 From: agent-db0ec53c058f1326 Date: Fri, 17 Apr 2026 00:52:17 +0200 Subject: [PATCH] build(agent): molt-z#db0ec5 iteration --- README.md | 33 ++++++++++++------- gridverse/adapter_marketplace/__init__.py | 14 ++++++-- .../building_heating_adapter.py | 3 ++ .../building_load_adapter.py | 19 +++++++++++ .../der_inverter_adapter.py | 22 +++++++++++++ gridverse/energi_bridge.py | 12 ++++--- gridverse/registry.py | 17 ++++++++++ 7 files changed, 100 insertions(+), 20 deletions(-) create mode 100644 gridverse/adapter_marketplace/building_load_adapter.py create mode 100644 gridverse/adapter_marketplace/der_inverter_adapter.py diff --git a/README.md b/README.md index 36ac20d..06f6056 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,25 @@ -# GridVerse Open Low-Code Platform (MVP) +GridVerse Open Low-Code Platform -This repository implements a minimal, production-ready MVP scaffold for GridVerse: a cross-domain energy optimization platform with a graph-contract registry and an adapter marketplace. +Overview +- GridVerse is an open-source, cross-domain energy optimization platform. It provides: + - A Graph-Contract Registry for versioned data contracts + - An Adapter Marketplace for plug-and-play cross-domain adapters + - A tiny ADMM-like solver and delta-sync protocol for distributed optimization + - A canonical EnergiBridge to translate between GridVerse primitives and a vendor-agnostic IR -- Core contracts: LocalProblem, SharedVariables, PlanDelta, ConstraintSet, DeviceInfo -- Simple registry for versioned contracts -- Two starter adapters (DER inverter and building heating controller) -- A toy ADMM-like solver and delta-sync mechanism -- Tests and packaging configuration to ensure reproducible builds +Architecture (highlights) +- gridverse.contracts: LocalProblem, SharedVariables, PlanDelta, ConstraintSet, DeviceInfo +- gridverse.registry: GraphContractRegistry +- gridverse.adapter_marketplace: starter adapters and skeleton interface +- gridverse.solver / gridverse.delta_sync: lightweight solver and offline sync +- EnergiBridge: canonical bridge for cross-domain interoperability -Usage -- Run tests and build: `bash test.sh` -- Explore the package under `gridverse/` and `gridverse/adapter_marketplace/` +How to run +- `bash test.sh` to run tests and packaging checks +- Python packaging is defined in pyproject.toml -This MVP is intentionally small but production-oriented: small, well-tested units with clear APIs designed to be composed into a larger cross-domain orchestration stack. -- EnergiBridge Skeleton: A canonical bridge for mapping GridVerse primitives to a CatOpt-inspired IR, enabling cross-domain adapters and registries to interoperate. See gridverse/energi_bridge.py for details. +This repository includes starter adapters to bootstrap interoperability: +- DERInverterAdapter and BuildingLoadAdapter under gridverse/adapter_marketplace + +Ready to publish signal +- Once all MVP components are validated, a READY_TO_PUBLISH file will be created at the repo root. diff --git a/gridverse/adapter_marketplace/__init__.py b/gridverse/adapter_marketplace/__init__.py index 26d178a..f84117c 100644 --- a/gridverse/adapter_marketplace/__init__.py +++ b/gridverse/adapter_marketplace/__init__.py @@ -1,4 +1,12 @@ -from .der_inverter import DERInverterAdapter, DERAdapter -from .building_heating_controller import BuildingHeatingAdapter, HeatingAdapter +"""Adapter Marketplace skeleton for GridVerse MVP.""" -__all__ = ["DERInverterAdapter", "DERAdapter", "BuildingHeatingAdapter", "HeatingAdapter"] +# Primary adapter implementations +from .der_inverter_adapter import DERInverterAdapter +from .building_load_adapter import BuildingLoadAdapter + +# Compatibility aliases expected by tests +# Provide backward-compatible/public API aliases for common names +from .der_inverter import DERAdapter +from .building_heating_adapter import BuildingHeatingAdapter as HeatingAdapter + +__all__ = ["DERInverterAdapter", "BuildingLoadAdapter", "DERAdapter", "HeatingAdapter"] diff --git a/gridverse/adapter_marketplace/building_heating_adapter.py b/gridverse/adapter_marketplace/building_heating_adapter.py index 8146275..d71258f 100644 --- a/gridverse/adapter_marketplace/building_heating_adapter.py +++ b/gridverse/adapter_marketplace/building_heating_adapter.py @@ -14,3 +14,6 @@ class BuildingHeatingAdapter: current_temp = problem.variables.get("indoor_temp", 20) signals = {"heating_delta": max(0.0, 22.0 - current_temp)} return SharedVariables(signals=signals, version=1) + + def contract(self) -> Dict[str, str]: + return {"name": "HeatingAdapter", "version": "0.1"} diff --git a/gridverse/adapter_marketplace/building_load_adapter.py b/gridverse/adapter_marketplace/building_load_adapter.py new file mode 100644 index 0000000..9938bd5 --- /dev/null +++ b/gridverse/adapter_marketplace/building_load_adapter.py @@ -0,0 +1,19 @@ +from typing import Dict, Any + +from gridverse.energi_bridge import EnergiBridge + +class BuildingLoadAdapter: + """ + Starter Adapter: Building-level Heating/Cooling Load Controller + - Translates building load contracts to IR for the registry. + """ + name = "BuildingLoadAdapter" + version = "0.1" + + def to_ir(self, local_problem: Dict[str, Any]) -> Dict[str, Any]: + contract_type = "LocalProblem" + return EnergiBridge.to_ir(contract_type, local_problem) + + @classmethod + def conformance(cls) -> Dict[str, str]: + return {"name": cls.name, "version": cls.version} diff --git a/gridverse/adapter_marketplace/der_inverter_adapter.py b/gridverse/adapter_marketplace/der_inverter_adapter.py new file mode 100644 index 0000000..bfea14e --- /dev/null +++ b/gridverse/adapter_marketplace/der_inverter_adapter.py @@ -0,0 +1,22 @@ +from typing import Dict, Any + +from gridverse.energi_bridge import EnergiBridge + +class DERInverterAdapter: + """ + Starter Adapter: DER Inverter Controller + - Maps local inverter state to GridVerse LocalProblem IR via EnergiBridge. + - Intended as a minimal, plug-and-play component for cross-domain tests. + """ + name = "DERInverterAdapter" + version = "0.1" + + def to_ir(self, local_problem: Dict[str, Any]) -> Dict[str, Any]: + """Convert a LocalProblem payload to an IR representation.""" + contract_type = "LocalProblem" + return EnergiBridge.to_ir(contract_type, local_problem) + + @classmethod + def conformance(cls) -> Dict[str, str]: + """Return a minimal conformance hint for registry checks.""" + return {"name": cls.name, "version": cls.version} diff --git a/gridverse/energi_bridge.py b/gridverse/energi_bridge.py index 8d2032b..4850c63 100644 --- a/gridverse/energi_bridge.py +++ b/gridverse/energi_bridge.py @@ -20,7 +20,7 @@ class EnergiBridge: """ @staticmethod - def to_ir(contract_type: str, payload: Dict[str, Any]) -> Dict[str, Any]: + def to_ir(contract_type: str, payload: Dict[str, Any], metadata: Dict[str, Any] = None) -> Dict[str, Any]: """Convert a GridVerse contract into a canonical IR payload. Args: @@ -31,13 +31,15 @@ class EnergiBridge: A dict representing the IR contract, suitable for transport or storage in the registry. This is intentionally lightweight. """ + if metadata is None: + metadata = { + "source": "gridverse", + "version": "0.1", + } return { "ir_type": contract_type, "ir_payload": payload, - "metadata": { - "source": "gridverse", - "version": "0.1", - }, + "metadata": metadata, } @staticmethod diff --git a/gridverse/registry.py b/gridverse/registry.py index 96639ce..205fc87 100644 --- a/gridverse/registry.py +++ b/gridverse/registry.py @@ -36,6 +36,23 @@ class GraphContractRegistry: contracts_ok = self._contracts.get(contract_key) is not None return adapters_ok and contracts_ok + # Extended API: support metadata-aware contract registration without breaking + # existing callers. This enables per-message auditing and replay protection. + def register_contract_with_meta(self, contract_type: str, version: str, payload: Dict[str, Any], metadata: Dict[str, Any] | None = None) -> None: + if not hasattr(self, "_contracts"): + self._contracts = {} + self._contracts[(contract_type, version)] = { + "payload": payload, + "metadata": metadata or {}, + } + + def get_contract_with_meta(self, contract_type: str, version: str) -> Dict[str, Any]: + entry = self._contracts.get((contract_type, version)) + if isinstance(entry, dict) and "payload" in entry: + return entry + # Fallback to legacy payload storage if present + return {"payload": entry, "metadata": {}} + class ContractRegistry: """Backward-compatible, simplified registry interface used by tests.