From cf16b2aeb23b0947db1f2ded74ed20c310d7f6a9 Mon Sep 17 00:00:00 2001 From: agent-db0ec53c058f1326 Date: Wed, 15 Apr 2026 20:20:57 +0200 Subject: [PATCH] build(agent): molt-z#db0ec5 iteration --- README.md | 1 + nova_plan/catopt_bridge.py | 26 ++++++++++++++++++++ tests/test_catopt_bridge.py | 49 +++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 tests/test_catopt_bridge.py diff --git a/README.md b/README.md index 6fea45d..3457698 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ New scaffold: CatOpt Bridge (scaffold) - A lightweight scaffold to map NovaPlan primitives to a CatOpt-like representation. - Provides small building blocks: Object (local problem), Morphism (shared signals), and Functor (adapter interfaces). - The bridge is intentionally minimal to enable quick experimentation and cross-domain interoperability in MVP milestones. +- Practical notes: the bridge includes helpers to convert a LocalProblem into a canonical Object and to package a delta into a Morphism, enabling plug-and-play adapters across rover/habitat/satellite domains. It also exposes a small bridge_example utility to bootstrap experiments and verify interop in CI. A minimal, open-source MVP for decentralized, privacy-preserving multi-agent mission planning in deep-space robotic constellations. diff --git a/nova_plan/catopt_bridge.py b/nova_plan/catopt_bridge.py index 0b810d1..dad46d9 100644 --- a/nova_plan/catopt_bridge.py +++ b/nova_plan/catopt_bridge.py @@ -74,3 +74,29 @@ def protocol_example(local: LocalProblem) -> str: __all__ = ["Object", "Morphism", "Functor", "protocol_example"] + + +def to_object(local: LocalProblem) -> Object: + """Convenience helper: convert a LocalProblem into its canonical Object form.""" + return Object(local) + + +def to_morphism(delta: Dict[str, float], source: str, target: str, version: int = 1) -> Morphism: + """Convenience helper: produce a Morphism carrying an optimization delta.""" + return Morphism(delta=delta, source=source, target=target, version=version) + + +def bridge_example(local: LocalProblem, source: str = "rover", target: str = "habitat") -> Dict[str, Any]: + """Create a tiny bridge example: Object + Morphism for a given delta. + + Returns a simple dictionary combining both representations for easy testing + and experimentation in MVP pilots. + """ + obj = Object(local) + # small, illustrative delta: take current local variables as delta snapshot + delta = {k: v for k, v in local.variables.items()} + morph = Morphism(delta=delta, source=source, target=target, version=1) + return { + "object": obj.to_dict(), + "morphism": morph.to_json(), + } diff --git a/tests/test_catopt_bridge.py b/tests/test_catopt_bridge.py new file mode 100644 index 0000000..036a456 --- /dev/null +++ b/tests/test_catopt_bridge.py @@ -0,0 +1,49 @@ +import json +import pytest + +from nova_plan.dsl import LocalProblemDSL +from nova_plan.catopt_bridge import Object, Morphism, to_object, to_morphism, bridge_example + + +def test_local_problem_to_object_and_morphism_basic(): + # Create a minimal LocalProblem via DSL + dsl = LocalProblemDSL( + agent_id="rover1", + objective_expr='vars["x"]', + variables={"x": 1.5}, + constraints={}, + ) + lp = dsl.to_local_problem() + + # Convert to canonical object and verify structure + obj = to_object(lp) + od = obj.to_dict() + assert od["agent_id"] == "rover1" + assert od["variables"] == {"x": 1.5} + + # Create a morphism (delta) and serialize + delta = {"x": 0.25} + morph = to_morphism(delta, source="rover1", target="habitat", version=1) + j = morph.to_json() + data = json.loads(j) + assert data["source"] == "rover1" + assert data["target"] == "habitat" + assert data["delta"] == delta + + +def test_bridge_example_integration(): + dsl = LocalProblemDSL( + agent_id="habitat1", + objective_expr='vars["a"] + shared["b"]', + variables={"a": 2.0}, + constraints={} + ) + lp = dsl.to_local_problem() + res = bridge_example(lp, source="habitat1", target="rover1") + # Basic structure checks + assert "object" in res and isinstance(res["object"], dict) + assert "morphism" in res and isinstance(res["morphism"], str) + # Validate object payload keys + obj_payload = res["object"] + assert obj_payload["agent_id"] == "habitat1" + assert obj_payload["variables"] == {"a": 2.0}