diff --git a/AGENTS.md b/AGENTS.md index df1e12a..6887e76 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,3 +25,19 @@ CosmosMesh CatOpt bridge (MVP) - Starter adapters: rover and habitat module adapters exposing simple interfaces for readState, exposeLocalProblemData, and applyCommand. - Transport: TLS-based, e.g., MQTT/REST for prototyping. - Deliverables: a minimal CatOpt bridge module (src/cosmosmesh_privacy_preserving_federated/catopt_bridge.py), a small registry graph for contracts, and a DSL sketch to describe LocalProblem/SharedVariables/DualVariables/PlanDelta. +CosmosMesh GoC Bridge (Plan) +- Purpose: provide a canonical, vendor-agnostic interoperability layer that maps CosmosMesh primitives to a CatOpt-inspired intermediate representation (IR) to enable cross-domain adapters with minimal rework. +- Core concepts: + - Objects -> LocalProblems (per-asset planning state) + - Morphisms -> SharedVariables / DualVariables (versioned summaries, priors) + - PlanDelta -> incremental plan changes with cryptographic tags + - TimeMonoid / Metadata -> per-message timing, nonce, signatures for replay protection + - Graph-of-Contracts registry -> versioned data schemas and adapter conformance harness +- MVP wiring (8–12 weeks, 2–3 agents to start): + 1) Phase 0: protocol skeleton + 2 starter adapters (rover_planner, habitat_module) with TLS transport; lightweight ADMM-lite local solver; delta-sync with deterministic replay on reconnects; + 2) Phase 1: governance ledger scaffold; identity layer (DID/short-lived certs); secure aggregation for SharedVariables; adapter conformance tests. + 3) Phase 2: cross-domain demo in a simulated second domain; publish a CosmosMesh SDK and a canonical transport; toy contract examples and adapters. + 4) Phase 3: hardware-in-the-loop validation with Gazebo/ROS for 2–3 devices; KPI dashboards for convergence speed, delta-sync latency, auditability. +- Deliverables to align with repo: add a minimal goC_bridge.py (already added in this patch), a canonical registry, and a small DSL sketch for contracts. The initial implementation focuses on data models and conversion utilities to bootstrap adapters. +- Testing approach: unit tests for to_catopt/from_catopt conversions, registry registration, and adapter wiring stubs. End-to-end tests to verify end-to-end delta creation and metadata propagation on a simulated pair of agents. +- Open questions: confirm preferred identity scheme (DID vs short-lived certs) and transport (TLS over MQTT vs REST) for the MVP in your environment. diff --git a/README.md b/README.md index a4f4bab..f845bc6 100644 --- a/README.md +++ b/README.md @@ -47,4 +47,20 @@ CatOpt Bridge (MVP) - A small in-memory contract registry to version primitives and schemas. - DSL sketches for describing LocalProblem/SharedVariables/PlanDelta (for prototyping and testing). -- Usage example: see examples/catopt_demo.py for a quick end-to-end round-trip construction. + - Usage example: see examples/catopt_demo.py for a quick end-to-end round-trip construction. + +GoC Bridge (Canonical Interoperability) +- Purpose: provide a canonical, vendor-agnostic interoperability layer that maps CosmosMesh primitives to a CatOpt-inspired intermediate representation (IR). +- Core mappings: + - Objects -> LocalProblems (per-asset planning state) + - Morphisms -> SharedVariables / DualVariables (versioned summaries and priors) + - PlanDelta -> incremental plan changes with cryptographic tags + - TimeMonoid and per-message Metadata for timing, nonce, and replay protection + - Graph-of-Contracts registry for adapters and data schemas with a conformance harness +- MVP wiring (8–12 weeks, 2–3 agents to start): + 1) Phase 0: protocol skeleton + 2 starter adapters (rover_planner, habitat_module) with TLS transport; a lightweight ADMM-lite local solver; end-to-end delta-sync with deterministic replay on reconnects. + 2) Phase 1: governance ledger scaffold; identity layer (DID/short-lived certs); secure aggregation defaults for SharedVariables; adapter conformance tests. + 3) Phase 2: cross-domain demo in a simulated second domain; publish a CosmosMesh SDK and a canonical transport; toy contract example and adapters. + 4) Phase 3: hardware-in-the-loop validation with Gazebo/ROS for 2–3 devices; KPI dashboards for convergence speed, delta-sync latency, and auditability. +- Deliverables to seed interoperability: a minimal goC_bridge.py (prototype), a CanonicalIR, and a small adapter registry for mapping CosmosMesh primitives. +- This section is a seed for cross-domain reuse and will be extended with real transport bindings and security layers in follow-on work. diff --git a/src/cosmosmesh_privacy_preserving_federated/goC_bridge.py b/src/cosmosmesh_privacy_preserving_federated/goC_bridge.py new file mode 100644 index 0000000..d571bf4 --- /dev/null +++ b/src/cosmosmesh_privacy_preserving_federated/goC_bridge.py @@ -0,0 +1,174 @@ +""" +Canonical GoC Bridge for CosmosMesh (prototype) + +This module provides a minimal, vendor-agnostic interoperability bridge +that maps CosmosMesh primitives to a CatOpt-inspired canonical representation +(IR: Objects, Morphisms, PlanDelta). It is intentionally lightweight to seed +adapter development and cross-domain experimentation. + +Note: This is a small, strongly-typed shim meant for MVP-level wiring. It does +not attempt to implement the full ADMM or transport layer; it focuses on data +structures and simple conversion utilities that adapters can reuse. +""" + +from __future__ import annotations + +from dataclasses import dataclass, asdict +from typing import Any, Dict, Optional + + +@dataclass +class LocalProblem: + id: str + assets: list[str] + objective: str + constraints: list[str] + data_contracts: Optional[Dict[str, Any]] = None + + def to_catopt(self) -> dict: + return { + "type": "LocalProblem", + "id": self.id, + "assets": self.assets, + "objective": self.objective, + "constraints": self.constraints, + "data_contracts": self.data_contracts or {}, + } + + +@dataclass +class SharedVariables: + vars: Dict[str, float] + version: int + + def to_catopt(self) -> dict: + return { + "type": "SharedVariables", + "version": self.version, + "vars": self.vars, + } + + +@dataclass +class PlanDelta: + delta: Dict[str, Any] + timestamp: float + author: str + contract_id: str + privacy_budget: float + metadata: Optional[Dict[str, Any]] = None + + def to_catopt(self) -> dict: + payload = { + "type": "PlanDelta", + "contract_id": self.contract_id, + "timestamp": self.timestamp, + "author": self.author, + "privacy_budget": self.privacy_budget, + "delta": self.delta, + } + if self.metadata: + payload["metadata"] = self.metadata + return payload + + +@dataclass +class Metadata: + version: int + timestamp: float + signature: str + nonce: str + + def to_catopt(self) -> dict: + return { + "version": self.version, + "timestamp": self.timestamp, + "signature": self.signature, + "nonce": self.nonce, + } + + +class CanonicalIR: + """Very small, typed IR for CatOpt-like interop. + + This is a lightweight representation of the cross-domain primitives. The + real system would use a more feature-rich IR and a transport layer. + """ + + def __init__(self) -> None: + self.contracts: Dict[str, Dict[str, Any]] = {} + + def register_contract(self, contract_id: str, payload: Dict[str, Any]) -> None: + self.contracts[contract_id] = payload + + def to_dict(self) -> Dict[str, Any]: + return {"contracts": self.contracts} + + +class GoCBridgeRegistry: + """Lightweight registry for adapters and contract schemas.""" + + def __init__(self) -> None: + self.adapters: Dict[str, Any] = {} + self.ir = CanonicalIR() + + def register_adapter(self, contract_id: str, adapter: Any) -> None: + self.adapters[contract_id] = adapter + + def get_adapter(self, contract_id: str) -> Optional[Any]: + return self.adapters.get(contract_id) + + def register_contract_schema(self, contract_id: str, payload: Dict[str, Any]) -> None: + self.ir.register_contract(contract_id, payload) + + def registry_summary(self) -> Dict[str, Any]: + return { + "adapters": list(self.adapters.keys()), + "contracts": list(self.ir.contracts.keys()), + } + + +def to_catopt(obj: Any) -> Optional[dict]: + """Convert a CosmosMesh primitive to a minimal CatOpt-like dict.""" + if isinstance(obj, LocalProblem) or isinstance(obj, SharedVariables) or isinstance(obj, PlanDelta): + return obj.to_catopt() + if hasattr(obj, "to_catopt"): + return getattr(obj, "to_catopt")() + return None + + +def from_catopt(payload: Dict[str, Any]) -> Any: + """Create a domain object from a CatOpt-like payload (minimal subset).""" + t = payload.get("type") + if t == "LocalProblem": + return LocalProblem( + id=payload.get("id", ""), + assets=payload.get("assets", []), + objective=payload.get("objective", ""), + constraints=payload.get("constraints", []), + data_contracts=payload.get("data_contracts"), + ) + if t == "SharedVariables": + return SharedVariables(vars=payload.get("vars", {}), version=payload.get("version", 0)) + if t == "PlanDelta": + return PlanDelta( + delta=payload.get("delta", {}), + timestamp=payload.get("timestamp", 0.0), + author=payload.get("author", ""), + contract_id=payload.get("contract_id", ""), + privacy_budget=payload.get("privacy_budget", 0.0), + metadata=payload.get("metadata"), + ) + return None + + +__all__ = [ + "LocalProblem", + "SharedVariables", + "PlanDelta", + "Metadata", + "CanonicalIR", + "GoCBridgeRegistry", + "to_catopt", + "from_catopt", +]