From 4ceadb2ab085ee93c31a9631eac8dbab9ee6ad39 Mon Sep 17 00:00:00 2001 From: agent-14fd4b738639d573 Date: Fri, 24 Apr 2026 20:12:22 +0200 Subject: [PATCH] build(agent): melter#14fd4b iteration --- mercurymesh/schema.py | 66 +++++++++++++++++++++++++++++++++ tests/test_schema_and_bridge.py | 45 ++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 mercurymesh/schema.py create mode 100644 tests/test_schema_and_bridge.py diff --git a/mercurymesh/schema.py b/mercurymesh/schema.py new file mode 100644 index 0000000..f2b3eb6 --- /dev/null +++ b/mercurymesh/schema.py @@ -0,0 +1,66 @@ +"""IR schema exporter and sample payloads for conformance tests. + +Provides small helpers to extract Pydantic JSON schemas for the +EnergiBridge-style IR models and to produce small example payloads. +""" +from __future__ import annotations + +from typing import Dict, Any +import json + +from . import ir + + +def get_ir_schemas() -> Dict[str, Any]: + """Return a mapping of IR model names to their JSON schema (as dicts).""" + schemas: Dict[str, Any] = {} + # Intentionally export a small, curated set of models used in the + # interoperability layer. + models = [ + ir.LocalMarketContext, + ir.AggregatedSignalIR, + ir.PlanDeltaIR, + ir.DualVariables, + ir.PrivacyBudgetEntry, + ir.AuditLogEntry, + ir.TimeRound, + ir.GoCRegistryEntry, + ] + for m in models: + # pydantic BaseModel has .schema() + schemas[m.__name__] = m.schema() + return schemas + + +def sample_payloads() -> Dict[str, Any]: + """Return small example payloads for a few IR types. + + These are useful for documentation and quick conformance testing. + """ + now = "2020-01-01T00:00:00Z" + return { + "LocalMarketContext": { + "venue_id": "venue-a", + "symbol": "ABC", + "timeframe": "1m", + "objective": "liquidity", + "timestamp": now, + }, + "AggregatedSignalIR": { + "version": "v1", + "venues": ["venue-a", "venue-b"], + "feature_vector": {"liquidity_proxy": 0.75}, + "privacy_budget": 0.1, + }, + "PlanDeltaIR": { + "contract_id": "c1", + "author": "agent-1", + "timestamp": now, + "actions": {"adjust": "scale", "scale": 0.5}, + }, + } + + +def schemas_json() -> str: + """Return the IR schemas as a pretty-printed JSON string.""" + return json.dumps(get_ir_schemas(), indent=2, sort_keys=True) diff --git a/tests/test_schema_and_bridge.py b/tests/test_schema_and_bridge.py new file mode 100644 index 0000000..d79b990 --- /dev/null +++ b/tests/test_schema_and_bridge.py @@ -0,0 +1,45 @@ +from mercurymesh.schema import get_ir_schemas, sample_payloads +from mercurymesh.bridge_ir import to_ir_market_signal, to_ir_aggregated_signal +from mercurymesh.adapters.venue_a import VenueAAdapter +from mercurymesh.adapters.venue_b import VenueBAdapter + + +def test_ir_schemas_present(): + schemas = get_ir_schemas() + # Basic smoke checks for a few required IR models + assert "LocalMarketContext" in schemas + assert "AggregatedSignalIR" in schemas + assert "PlanDeltaIR" in schemas + + +def test_sample_payloads_shape(): + samples = sample_payloads() + assert "LocalMarketContext" in samples + assert "AggregatedSignalIR" in samples + + +def test_adapter_to_ir_translation(): + a = VenueAAdapter() + b = VenueBAdapter() + msa = a.extract_signal() + msb = b.extract_signal() + + ira = to_ir_market_signal(msa) + irb = to_ir_market_signal(msb) + # Ensure canonical wrapper keys exist + assert "local_context" in ira + assert "local_context" in irb + + # Build a simple AggregatedSignal-like dict for translation function + agg = { + "venues": [msa.venue_id, msb.venue_id], + "feature_vector": {**msa.features, **msb.features}, + "privacy_budget_used": 0.05, + "nonce": "n-1", + "merkle_proof": None, + } + + # Convert using the helper; ensure keys are present + out = to_ir_aggregated_signal(type("Agg", (), agg)()) + assert "aggregated" in out + assert "feature_vector" in out["aggregated"]