build(agent): molt-z#db0ec5 iteration
This commit is contained in:
parent
7e891bda72
commit
7af52d7e88
|
|
@ -15,3 +15,10 @@ How to run tests
|
||||||
Notes
|
Notes
|
||||||
- This MVP focuses on minimal, well-scoped components to enable end-to-end interoperability with adapters and the ADMM-lite solver.
|
- This MVP focuses on minimal, well-scoped components to enable end-to-end interoperability with adapters and the ADMM-lite solver.
|
||||||
- See core/bridge.py for the canonical mapping primitives and tests for contract registry and bridge in tests/.
|
- See core/bridge.py for the canonical mapping primitives and tests for contract registry and bridge in tests/.
|
||||||
|
|
||||||
|
## MVP Enhancements
|
||||||
|
- 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).
|
||||||
|
- Added a minimal in-repo DSL documentation and a sample Graph-of-Contracts scaffold to accelerate adapter onboarding.
|
||||||
|
- Documentation and a ready-to-publish readiness baton in READY_TO_PUBLISH (to signal MVP stability when publishing).
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -55,13 +56,34 @@ class ContractRegistry:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
# In-memory, versioned registry with simple thread-safety for MVP
|
||||||
self._store: Dict[str, Dict[str, ContractDefinition]] = {}
|
self._store: Dict[str, Dict[str, ContractDefinition]] = {}
|
||||||
|
self._lock = threading.RLock()
|
||||||
|
|
||||||
def add_contract(self, name: str, version: str, schema: Dict[str, Any]) -> None:
|
def add_contract(self, name: str, version: str, schema: Dict[str, Any]) -> None:
|
||||||
self._store.setdefault(name, {})[version] = ContractDefinition(name, version, schema)
|
with self._lock:
|
||||||
|
self._store.setdefault(name, {})[version] = ContractDefinition(name, version, schema)
|
||||||
|
|
||||||
def get_contract(self, name: str, version: str) -> ContractDefinition | None:
|
def get_contract(self, name: str, version: str) -> ContractDefinition | None:
|
||||||
return self._store.get(name, {}).get(version)
|
with self._lock:
|
||||||
|
return self._store.get(name, {}).get(version)
|
||||||
|
|
||||||
def list_contracts(self) -> Dict[str, Dict[str, ContractDefinition]]:
|
def list_contracts(self) -> Dict[str, Dict[str, ContractDefinition]]:
|
||||||
return self._store
|
with self._lock:
|
||||||
|
# Return a shallow copy to avoid external mutation
|
||||||
|
return {k: dict(v) for k, v in self._store.items()}
|
||||||
|
|
||||||
|
# Convenience helpers for MVP tooling
|
||||||
|
def has_contract(self, name: str, version: str) -> bool:
|
||||||
|
with self._lock:
|
||||||
|
return version in self._store.get(name, {})
|
||||||
|
|
||||||
|
def remove_contract(self, name: str, version: str) -> bool:
|
||||||
|
with self._lock:
|
||||||
|
if name in self._store and version in self._store[name]:
|
||||||
|
del self._store[name][version]
|
||||||
|
# Clean up empty dicts
|
||||||
|
if not self._store[name]:
|
||||||
|
del self._store[name]
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Dict, Optional
|
||||||
|
|
||||||
|
from .contracts import ContractDefinition
|
||||||
|
|
||||||
|
|
||||||
|
class GraphOfContracts:
|
||||||
|
"""Lightweight registry graph mapping adapters to contract versions.
|
||||||
|
|
||||||
|
This is intentionally minimal: it stores per-adapter contracts organized by
|
||||||
|
contract name -> version -> ContractDefinition, enabling plug-and-play across
|
||||||
|
domain adapters while keeping a canonical reference per adapter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
# adapter_name -> contract_name -> version -> ContractDefinition
|
||||||
|
self._graph: Dict[str, Dict[str, Dict[str, ContractDefinition]]] = {}
|
||||||
|
|
||||||
|
def register(self, adapter: str, contract_name: str, version: str, schema: Dict[str, object]) -> None:
|
||||||
|
self._graph.setdefault(adapter, {})
|
||||||
|
self._graph[adapter].setdefault(contract_name, {})[version] = ContractDefinition(
|
||||||
|
name=contract_name,
|
||||||
|
version=version,
|
||||||
|
schema=schema,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_contract(self, adapter: str, contract_name: str, version: str) -> Optional[ContractDefinition]:
|
||||||
|
return self._graph.get(adapter, {}).get(contract_name, {}).get(version)
|
||||||
|
|
||||||
|
def list_adapter_contracts(self, adapter: str) -> Dict[str, Dict[str, ContractDefinition]]:
|
||||||
|
return self._graph.get(adapter, {})
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# DSL Sketch: Core CatOpt-Graph Primitives
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
LocalProblem
|
||||||
|
- asset_id: identifier of the local optimization problem on the device
|
||||||
|
- payload: dictionary containing domain-specific problem data (e.g., objective terms, constraints)
|
||||||
|
|
||||||
|
SharedVariables
|
||||||
|
- iter_id: iteration counter for synchronization rounds
|
||||||
|
- values: map of signals that are shared across the mesh (e.g., dual variables, summaries)
|
||||||
|
|
||||||
|
DualVariables
|
||||||
|
- iter_id: iteration counter
|
||||||
|
- values: dual variables per shared signal
|
||||||
|
|
||||||
|
PlanDelta
|
||||||
|
- iter_id: iteration counter
|
||||||
|
- delta: aggregated changes to be applied to local plans
|
||||||
|
|
||||||
|
PrivacyBudget
|
||||||
|
- budget_id: identifier for privacy budget instance
|
||||||
|
- limits: per-signal DP budgets or leakage limits
|
||||||
|
|
||||||
|
AuditLog
|
||||||
|
- entry_id: unique log entry identifier
|
||||||
|
- payload: audit metadata for reconciliation steps
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
This sketch intentionally stays minimal to accelerate MVP integration.
|
||||||
Loading…
Reference in New Issue