From 9cd3106e4f56eafbcf4a72c42f0d957636d7ff18 Mon Sep 17 00:00:00 2001 From: agent-cb502d7656738cf6 Date: Wed, 15 Apr 2026 02:05:15 +0200 Subject: [PATCH] build(agent): molt-d#cb502d iteration --- .../__init__.py | 18 ++-- .../catopt_bridge.py | 88 +++++++------------ .../contract_registry.py | 34 +++++++ tests/test_catopt_bridge.py | 21 +++++ 4 files changed, 93 insertions(+), 68 deletions(-) create mode 100644 src/cosmosmesh_privacy_preserving_federated_/contract_registry.py create mode 100644 tests/test_catopt_bridge.py diff --git a/src/cosmosmesh_privacy_preserving_federated_/__init__.py b/src/cosmosmesh_privacy_preserving_federated_/__init__.py index 033a3b1..59f5831 100644 --- a/src/cosmosmesh_privacy_preserving_federated_/__init__.py +++ b/src/cosmosmesh_privacy_preserving_federated_/__init__.py @@ -1,18 +1,10 @@ -"""CosmosMesh MVP: minimal Python package scaffold. +"""Public API for the CatOpt bridge MVP within the CosmosMesh core package.""" -This file provides a tiny API surface to satisfy the existing unit tests. -The full CosmosMesh MVP will progressively replace this with a richer API -covering LocalProblem / SharedVariables / PlanDelta contracts and a tiny -ADMM-lite solver, but for now we expose a single utility used by tests. -""" +from .catopt_bridge import CatOptBridge +from .contract_registry import REGISTRY, register_contract, get_contract def add(a, b): - """Return the sum of two numbers. - - This is a placeholder utility to bootstrap the package API surface for - the MVP. It is deliberately simple and well-documented. - """ + """Tiny compatibility helper used by tests.""" return a + b - -__all__ = ["add"] +__all__ = ["CatOptBridge", "REGISTRY", "register_contract", "get_contract", "add"] diff --git a/src/cosmosmesh_privacy_preserving_federated_/catopt_bridge.py b/src/cosmosmesh_privacy_preserving_federated_/catopt_bridge.py index 862f9bf..4a4eb2a 100644 --- a/src/cosmosmesh_privacy_preserving_federated_/catopt_bridge.py +++ b/src/cosmosmesh_privacy_preserving_federated_/catopt_bridge.py @@ -1,71 +1,49 @@ -"""CatOpt Bridge (lightweight interoperability layer). +"""Minimal CatOpt bridge scaffold for CosmosMesh. -This module provides a tiny, protocol-agnostic bridge that maps CosmosMesh MVP -primitives into a minimal CatOpt-like representation. It is intentionally small -and dependency-free to keep the MVP scaffold lightweight and safe for rapid -iteration. +This module provides a tiny translator layer that maps CosmosMesh primitives +into a canonical CatOpt-like representation. It is intentionally lightweight +and designed for MVP bootstrapping and testing. """ + from __future__ import annotations -from dataclasses import dataclass -from typing import Dict +from typing import Any, Dict -try: - # Local protocol primitives from the MVP scaffold - from .protocol import LocalProblem, SharedVariables, DualVariables -except Exception: # pragma: no cover - fallback for environments without protocol - LocalProblem = object # type: ignore - SharedVariables = object # type: ignore - DualVariables = object # type: ignore - - -@dataclass -class CatOptObject: - """Lightweight CatOpt Object representation for MVP bridging.""" - id: str - payload: Dict[str, float] - - -@dataclass -class CatOptMorphism: - """Lightweight CatOpt Morphism representation for MVP bridging.""" - name: str - mapping: Dict[str, float] +from .contract_registry import REGISTRY, register_contract, get_contract class CatOptBridge: - """Bridge that translates CosmosMesh primitives to a simple CatOpt-style map. - - This is deliberately minimal: it focuses on a stable, serializable mapping - suitable for prototyping adapters and does not implement a full formal - category-theory bridge. - """ - def __init__(self) -> None: - self._counter = 0 + # Public API surface is backed by the in-memory registry. + self._registry = REGISTRY - def map_local_problem(self, lp: LocalProblem) -> CatOptObject: - self._counter += 1 - # Use a simple, deterministic payload representation - payload = {k: float(v) if isinstance(v, (int, float)) else 0.0 for k, v in getattr(lp, 'variables', {}).items()} - return CatOptObject(id=f"lp-{self._counter}", payload=payload) + def register_contract(self, name: str, version: str, schema: Any) -> None: + # Lightweight pass-through to the registry + register_contract(name, version, schema) - def map_shared_variables(self, sv: SharedVariables) -> CatOptObject: - self._counter += 1 - payload = {k: float(v) for k, v in getattr(sv, 'signals', {}).items()} - return CatOptObject(id=f"sv-{self._counter}", payload=payload) + def get_contract(self, name: str) -> Any: + return get_contract(name) - def map_dual_variables(self, dv: DualVariables) -> CatOptObject: - self._counter += 1 - payload = {k: float(v) for k, v in getattr(dv, 'multipliers', {}).items()} - return CatOptObject(id=f"dv-{self._counter}", payload=payload) - - def to_catopt(self, lp: LocalProblem, sv: SharedVariables, dv: DualVariables) -> Dict[str, CatOptObject]: + # Translation helpers (toy implementations for MVP) + def translate_local_problem(self, local_problem: Dict[str, Any]) -> Dict[str, Any]: + # Expect a dict describing a LocalProblem; return a canonical representation return { - 'LocalProblem': self.map_local_problem(lp), - 'SharedVariables': self.map_shared_variables(sv), - 'DualVariables': self.map_dual_variables(dv), + "type": "LocalProblem", + "name": local_problem.get("name", ""), + "version": local_problem.get("version", "0.0.1"), + "variables": local_problem.get("variables", []), + "objective": local_problem.get("objective", None), + "constraints": local_problem.get("constraints", []), } + def translate_shared_variables(self, shared_vars: Dict[str, Any]) -> Dict[str, Any]: + return {"type": "SharedVariables", "vars": shared_vars} -__all__ = ["CatOptBridge", "CatOptObject", "CatOptMorphism"] + def translate_dual_variables(self, dual_vars: Dict[str, Any]) -> Dict[str, Any]: + return {"type": "DualVariables", "duals": dual_vars} + + def translate_plan_delta(self, plan_delta: Dict[str, Any]) -> Dict[str, Any]: + return {"type": "PlanDelta", "delta": plan_delta} + + +__all__ = ["CatOptBridge"] diff --git a/src/cosmosmesh_privacy_preserving_federated_/contract_registry.py b/src/cosmosmesh_privacy_preserving_federated_/contract_registry.py new file mode 100644 index 0000000..f6cf44f --- /dev/null +++ b/src/cosmosmesh_privacy_preserving_federated_/contract_registry.py @@ -0,0 +1,34 @@ +"""Lightweight in-memory contract registry for CatOpt bridge. + +This module exposes a simple Registry API to store versioned contracts +used by the CatOpt bridge for interoperability. +""" + +from typing import Any, Dict, Optional + + +class ContractRegistry: + def __init__(self) -> None: + # Map contract name -> {"version": str, "schema": Any} + self._contracts: Dict[str, Dict[str, Any]] = {} + + def register(self, name: str, version: str, schema: Any) -> None: + self._contracts[name] = {"version": version, "schema": schema} + + def get(self, name: str) -> Optional[Dict[str, Any]]: + return self._contracts.get(name) + + def all(self) -> Dict[str, Dict[str, Any]]: + return dict(self._contracts) + + +# Public singleton registry instance used by the bridge +REGISTRY = ContractRegistry() + + +def register_contract(name: str, version: str, schema: Any) -> None: + REGISTRY.register(name, version, schema) + + +def get_contract(name: str) -> Optional[Dict[str, Any]]: + return REGISTRY.get(name) diff --git a/tests/test_catopt_bridge.py b/tests/test_catopt_bridge.py new file mode 100644 index 0000000..a8f18a3 --- /dev/null +++ b/tests/test_catopt_bridge.py @@ -0,0 +1,21 @@ +import pytest + +from cosmosmesh_privacy_preserving_federated_.catopt_bridge import CatOptBridge +from cosmosmesh_privacy_preserving_federated_.contract_registry import REGISTRY + + +def test_registry_and_translation(): + bridge = CatOptBridge() + # Register a simple contract and verify registry exposure + bridge.register_contract("LocalProblem", "0.1.0", {"schema": {"type": "object"}}) + assert REGISTRY.get("LocalProblem")["version"] == "0.1.0" + + # Translate a minimal local problem description + local_problem = { + "name": "TestProblem", + "variables": [{"name": "x", "domain": "R"}], + "objective": {"type": "quadratic"}, + } + translated = bridge.translate_local_problem(local_problem) + assert translated["type"] == "LocalProblem" + assert translated["name"] == "TestProblem"