From 1923124962d01a803934392459cef542161a7ac8 Mon Sep 17 00:00:00 2001 From: agent-14fd4b738639d573 Date: Fri, 24 Apr 2026 18:05:56 +0200 Subject: [PATCH] build(agent): melter#14fd4b iteration --- mercurymesh/bridge_ir.py | 4 ++- mercurymesh/ir.py | 58 ++++++++++++++++++++++++++++++++++++++++ tests/test_ir.py | 58 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 mercurymesh/ir.py create mode 100644 tests/test_ir.py diff --git a/mercurymesh/bridge_ir.py b/mercurymesh/bridge_ir.py index afbcf0d..75ee96c 100644 --- a/mercurymesh/bridge_ir.py +++ b/mercurymesh/bridge_ir.py @@ -12,13 +12,15 @@ def to_ir_market_signal(ms: MarketSignal) -> Dict[str, object]: and demonstrations. It does not alter the original data model; it's a serializable view suitable for cross-venue adapters. """ + # Keep representation minimal and defensive: MarketSignal may not expose a + # version field at this time, so avoid reading it directly. return { "local_context": { "venue": ms.venue_id, "instrument": ms.symbol, "timestamp": ms.timestamp.isoformat(), "features": ms.features, - "version": ms.version, + "version": None, } } diff --git a/mercurymesh/ir.py b/mercurymesh/ir.py new file mode 100644 index 0000000..a846314 --- /dev/null +++ b/mercurymesh/ir.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from typing import Dict, List, Optional, Any +from datetime import datetime +from pydantic import BaseModel + + +class LocalMarketContext(BaseModel): + venue_id: str + symbol: str + timeframe: Optional[str] = None + objective: Optional[str] = None + timestamp: datetime + + +class AggregatedSignalIR(BaseModel): + version: str + venues: List[str] + feature_vector: Dict[str, float] + privacy_budget: Optional[float] = None + nonce: Optional[str] = None + merkle_root: Optional[str] = None + + +class PlanDeltaIR(BaseModel): + contract_id: str + author: Optional[str] + timestamp: datetime + actions: Dict[str, Any] + + +class DualVariables(BaseModel): + multipliers: Dict[str, float] + + +class PrivacyBudgetEntry(BaseModel): + signal_class: str + budget: float + expiry: Optional[datetime] = None + + +class AuditLogEntry(BaseModel): + entry: str + signer: Optional[str] + timestamp: datetime + contract_id: Optional[str] + + +class TimeRound(BaseModel): + round_id: str + start_ts: datetime + end_ts: datetime + + +class GoCRegistryEntry(BaseModel): + adapter_id: str + supported_domains: List[str] + contract_version: str diff --git a/tests/test_ir.py b/tests/test_ir.py new file mode 100644 index 0000000..d338cc1 --- /dev/null +++ b/tests/test_ir.py @@ -0,0 +1,58 @@ +from datetime import datetime, timedelta + +from mercurymesh.ir import ( + LocalMarketContext, + AggregatedSignalIR, + PlanDeltaIR, + DualVariables, + PrivacyBudgetEntry, + AuditLogEntry, + TimeRound, + GoCRegistryEntry, +) + + +def test_local_market_context_and_roundtrip(): + now = datetime.utcnow() + ctx = LocalMarketContext( + venue_id="venue-a", + symbol="XYZ", + timeframe="1m", + objective="liquidity", + timestamp=now, + ) + assert ctx.venue_id == "venue-a" + assert ctx.timestamp == now + + +def test_aggregated_signal_ir_and_plan_delta(): + now = datetime.utcnow() + agg = AggregatedSignalIR( + version="v1", + venues=["venue-a", "venue-b"], + feature_vector={"liquidity_proxy": 0.7}, + privacy_budget=0.05, + nonce="n-1", + ) + pd = PlanDeltaIR( + contract_id="c1", + author="agent-1", + timestamp=now, + actions={"adjust": "scale", "scale": 0.5}, + ) + assert "liquidity_proxy" in agg.feature_vector + assert pd.contract_id == "c1" + + +def test_misc_ir_types(): + now = datetime.utcnow() + dv = DualVariables(multipliers={"alpha": 1.0}) + pb = PrivacyBudgetEntry(signal_class="liquidity", budget=1.0, expiry=now) + al = AuditLogEntry(entry="created", signer="auditor", timestamp=now, contract_id="c1") + tr = TimeRound(round_id="r1", start_ts=now, end_ts=now + timedelta(seconds=60)) + reg = GoCRegistryEntry(adapter_id="a1", supported_domains=["feeds"], contract_version="v1") + assert dv.multipliers["alpha"] == 1.0 + assert pb.budget == 1.0 + assert al.signer == "auditor" + assert tr.end_ts > tr.start_ts + assert reg.contract_version == "v1"