From c1c701b0b668a1659912130ee92cd8fc4c372408 Mon Sep 17 00:00:00 2001 From: agent-7e3bbc424e07835b Date: Sun, 19 Apr 2026 20:22:38 +0200 Subject: [PATCH] build(agent): new-agents-2#7e3bbc iteration --- README.md | 5 ++++ core/__init__.py | 1 + core/energi_bridge.py | 66 +++++++++++++++++++++++++++++++++++++++++++ docs/dsl_sketch.md | 64 ++++++++++++++++++++++++----------------- 4 files changed, 110 insertions(+), 26 deletions(-) create mode 100644 core/energi_bridge.py diff --git a/README.md b/README.md index 01abf4a..a8687b9 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,11 @@ Notes - See core/bridge.py for the canonical mapping primitives and tests for contract registry and bridge in tests/. ## MVP Enhancements +- Added EnergiBridge: a minimal bridge to map domain LocalProblem representations to a canonical IR and back, enabling adapters to plug into the CatOpt-Graph core with a consistent interface. +- Exposed EnergiBridge in core as a convenient import (EnergiBridge). +- Added a minimal DSL sketch (docs/dsl_sketch.md) to seed adapters with canonical primitives. +- Introduced a lightweight Graph-of-Contracts scaffold and thread-safe contract registry improvements in core/core modules (see core/graph_of_contracts.py and core/contract_registry.py). +- Created READY_TO_PUBLISH baton for publishing readiness. - Added a lightweight Graph-of-Contracts in core/graph_of_contracts.py to map adapters to versioned contracts. - Added a minimal thread-safe enhancement to ContractRegistry (core/contracts.py) for concurrency safety. - Added a minimal DSL sketch documenting the LocalProblem/SharedVariables/PlanDelta data contracts (docs/dsl_sketch.md). diff --git a/core/__init__.py b/core/__init__.py index d2a956c..bba5417 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1 +1,2 @@ # Core primitives package for CatOpt-Graph MVP +from .energi_bridge import EnergiBridge # re-export for convenient imports diff --git a/core/energi_bridge.py b/core/energi_bridge.py new file mode 100644 index 0000000..c3fecb5 --- /dev/null +++ b/core/energi_bridge.py @@ -0,0 +1,66 @@ +from __future__ import annotations + +from typing import Any, Dict, Optional + +# Minimal EnergiBridge: bridge between domain LocalProblem representations and +# a canonical CatOpt-Graph IR. This is intentionally small and MVP-friendly to +# accelerate adapters onboarding and interoperability testing. + + +class EnergiBridge: + """Static helpers to map between LocalProblem domain objects and canonical IR.""" + + @staticmethod + def to_canonical(local_problem: Any) -> Dict[str, Any]: + """Convert a domain LocalProblem object into a canonical LocalProblem IR. + + The function is defensive: it accepts either a dict-like object or a + simple object with attributes. It returns a dict compatible with the + tests in this repository and the existing bridge layer. + """ + # If it's already a dict-like object + if isinstance(local_problem, dict): + lp_id = local_problem.get("id") or local_problem.get("asset_id") + domain = local_problem.get("domain", "unknown") + objective = local_problem.get("objective") + variables = local_problem.get("variables", {}) + payload = local_problem.get("payload", {}) + else: + lp_id = getattr(local_problem, "asset_id", None) or getattr(local_problem, "id", None) + domain = getattr(local_problem, "domain", "unknown") + objective = getattr(local_problem, "objective", None) + # Prefer explicit variables attribute if present, otherwise payload + variables = getattr(local_problem, "variables", None) + if variables is None: + variables = getattr(local_problem, "payload", {}) + payload = getattr(local_problem, "payload", {}) + + return { + "LocalProblem": { + "id": lp_id, + "domain": domain, + "objective": objective, + "variables": variables, + } + } + + @staticmethod + def from_canonical(canonical: Dict[str, Any]) -> Any: + """Convert a canonical IR LocalProblem back into a domain LocalProblem object. + + If the canonical representation is not compatible, returns a simple + dictionary fallback. + """ + lp = canonical.get("LocalProblem") if canonical else None + if isinstance(lp, dict): + asset_id = lp.get("id") or lp.get("object_id") or lp.get("asset_id") + payload = lp.get("variables") if "variables" in lp else lp.get("payload", {}) + # Import LocalProblem from core.contracts lazily to avoid circular imports + try: + from .contracts import LocalProblem as DomainLocalProblem # type: ignore + + return DomainLocalProblem(asset_id=asset_id, payload=payload or {}) + except Exception: + return {"asset_id": asset_id, "payload": payload or {}} + # Fallback: return the input as-is + return canonical diff --git a/docs/dsl_sketch.md b/docs/dsl_sketch.md index 101f77c..26162b9 100644 --- a/docs/dsl_sketch.md +++ b/docs/dsl_sketch.md @@ -1,35 +1,47 @@ -# DSL Sketch: Core CatOpt-Graph Primitives +# DSL Sketch: CatOpt-Graph MVP -This document provides a minimal sketch for the DSL that describes LocalProblems, -SharedVariables, PlanDelta, and related contracts used by adapters and the ADMM-lite -core. +This document provides a minimal DSL sketch to seed adapter implementers with +canonical data contracts for LocalProblem, SharedVariables, PlanDelta, and + DualVariables. The goal is to accelerate onboarding and ensure consistent + semantics across adapters. -LocalProblem -- asset_id: identifier of the local optimization problem on the device -- payload: dictionary containing domain-specific problem data (e.g., objective terms, constraints) +- Canonical primitives + - Objects: LocalProblem (assets, constraints, and objectives) + - Morphisms: SharedVariables (versioned signals exchanged between agents) + - DualVariables: Lagrange multipliers coordinating cross-adapter objectives + - PlanDelta: incremental plan changes with timestamp and signature + - PrivacyBudget, AuditLog: governance scaffolds +- Time modelling + - TimeMonoid: rounds with delta-sync semantics to support islanding and reconnection +- Registry + - Graph-of-Contracts (GoC): per-adapter contract versions with semantics and conformance rules -SharedVariables -- iter_id: iteration counter for synchronization rounds -- values: map of signals that are shared across the mesh (e.g., dual variables, summaries) +Seed DSL snippet (Python-like pseudo-DSL for onboarding): -DualVariables -- iter_id: iteration counter -- values: dual variables per shared signal + LocalProblem { + asset_id: str + domain: str + objective: dict + variables: dict + } -PlanDelta -- iter_id: iteration counter -- delta: aggregated changes to be applied to local plans + SharedVariables { + iter_id: int + values: dict + } -PrivacyBudget -- budget_id: identifier for privacy budget instance -- limits: per-signal DP budgets or leakage limits + PlanDelta { + iter_id: int + delta: dict + } -AuditLog -- entry_id: unique log entry identifier -- payload: audit metadata for reconciliation steps + DualVariables { + iter_id: int + values: dict + } -Notes -- All messages should include per-message metadata (version, timestamp, nonce, crypto-tag). -- Identity should be established via DIDs or short-lived certificates; transport should be TLS-secured. + PrivacyBudget { budget_id: str, limits: dict } + AuditLog { entry_id: str, payload: dict } -This sketch intentionally stays minimal to accelerate MVP integration. +This sketch is intentionally compact; implementers should map their domain data +structures into this canonical form via EnergiBridge-like adapters.