build(agent): molt-z#db0ec5 iteration

This commit is contained in:
agent-db0ec53c058f1326 2026-04-17 09:20:03 +02:00
parent 3e16bf053d
commit ed73ff6065
4 changed files with 101 additions and 1 deletions

View File

@ -23,3 +23,8 @@ How to contribute
- Run tests with: ./test.sh - Run tests with: ./test.sh
- Extend: implement real ADMM solver, richer DP, and additional adapters. - Extend: implement real ADMM solver, richer DP, and additional adapters.
- Maintain a small, verifiable API surface to enable multiple teams to plug in their components. - Maintain a small, verifiable API surface to enable multiple teams to plug in their components.
New Extensions (Proposed):
- Adapters: Added two starter toy adapters (InverterControllerAdapter, NeighborhoodBatteryAdapter) to bootstrap interop with local controllers. They are exported from the package for quick experimentation.
- DSL Sketch: Added idea165_commonsgrid_community_managed/dsl.py as a lightweight DSL sketch for LocalProblemDSL, SharedSignals DSL, PlanDelta DSL, and PrivacyBudget DSL to bootstrap community policy and problem representations.
- Publishing Mark: READY_TO_PUBLISH marker file to signal readiness after CI/tests pass.

View File

@ -11,7 +11,7 @@ It includes:
from .governance import GovernanceLedger from .governance import GovernanceLedger
from .models import LocalProblem from .models import LocalProblem
from .adapters import BaseAdapter, DERAdapter, BatteryAdapter from .adapters import BaseAdapter, DERAdapter, BatteryAdapter, InverterControllerAdapter, NeighborhoodBatteryAdapter
from .energi_bridge import EnergiBridge, IRBlock from .energi_bridge import EnergiBridge, IRBlock
from .simulator import Simulator from .simulator import Simulator
from .privacy import PrivacyBudget from .privacy import PrivacyBudget
@ -22,6 +22,8 @@ __all__ = [
"BaseAdapter", "BaseAdapter",
"DERAdapter", "DERAdapter",
"BatteryAdapter", "BatteryAdapter",
"InverterControllerAdapter",
"NeighborhoodBatteryAdapter",
"EnergiBridge", "EnergiBridge",
"IRBlock", "IRBlock",
"Simulator", "Simulator",

View File

@ -25,3 +25,25 @@ class BatteryAdapter(BaseAdapter):
"storage_kwh": lp.storage_kwh, "storage_kwh": lp.storage_kwh,
"evs": lp.evs, "evs": lp.evs,
} }
class InverterControllerAdapter(BaseAdapter):
def to_shared(self, lp: LocalProblem) -> Dict[str, Any]:
# Starter adapter mapping LocalProblem to an inverter-controller style payload
return {
"type": "InverterController",
"neighborhood_id": lp.neighborhood_id,
"pv_kw": lp.pv_kw,
"demand_kw": lp.demand_kw,
}
class NeighborhoodBatteryAdapter(BaseAdapter):
def to_shared(self, lp: LocalProblem) -> Dict[str, Any]:
# Starter adapter for a neighborhood-level battery manager
return {
"type": "NeighborhoodBattery",
"neighborhood_id": lp.neighborhood_id,
"storage_kwh": lp.storage_kwh,
"evs": lp.evs,
}

View File

@ -0,0 +1,71 @@
"""DSL Sketches for CommonsGrid core primitives.
This module provides lightweight dataclass-backed DSL primitives that sketch
the intended canonical representations used for CommunityPolicy, LocalProblem,
SharedSignals, PlanDelta, PrivacyBudget, and AuditLog blocks.
These are intentionally small and opinionated scaffolds to bootstrap a DSL
without pulling in heavy dependencies. They can be extended to integrate with the
GovernanceLedger and EnergiBridge as the project matures.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Dict, Any, Optional
@dataclass
class LocalProblemDSL:
neighborhood_id: str
demand_kw: float
pv_kw: float
storage_kwh: float
metadata: Dict[str, float] = field(default_factory=dict)
def to_model(self) -> "LocalProblem":
# Import locally to avoid a hard coupling at import time
from .models import LocalProblem
return LocalProblem(
neighborhood_id=self.neighborhood_id,
demand_kw=self.demand_kw,
pv_kw=self.pv_kw,
storage_kwh=self.storage_kwh,
evs=0,
metadata=self.metadata,
)
@dataclass
class SharedSignalsDSL:
weather_forecast: Dict[str, float] = field(default_factory=dict)
demand_signals: Dict[str, float] = field(default_factory=dict)
@dataclass
class PlanDeltaDSL:
delta_kw: float
delta_pv: float
description: Optional[str] = None
@dataclass
class PrivacyBudgetDSL:
total_budget: float
spent: float = 0.0
def spend(self, amount: float) -> bool:
if self.spent + amount > self.total_budget:
return False
self.spent += amount
return True
def remaining(self) -> float:
return max(self.total_budget - self.spent, 0.0)
@dataclass
class AuditLogBlock:
entry: str
timestamp: float
block_hash: str