build(agent): molt-x#ed374b iteration
This commit is contained in:
parent
69f0cddaa4
commit
9c2ce20262
|
|
@ -67,6 +67,40 @@ class GraphOfContracts:
|
|||
return self.contracts.get(contract_id)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SafetyBudget:
|
||||
"""Budget controls to enforce safety constraints across federation.
|
||||
|
||||
This is a lightweight, pluggable budget model for MVP. It captures a
|
||||
few conservative defaults and can be extended with domain-specific checks.
|
||||
"""
|
||||
enabled: bool = True
|
||||
max_current_draw_a: float = 0.0 # maximum allowed current draw in amperes
|
||||
max_voltage_variation_pu: float = 0.0 # per-unit allowable voltage variation
|
||||
device_limits: Dict[str, float] = field(default_factory=dict) # per-device limits
|
||||
timestamp: float = field(default_factory=time.time)
|
||||
|
||||
def update(self, key: str, value: Any) -> None:
|
||||
self.device_limits[key] = value
|
||||
self.timestamp = time.time()
|
||||
|
||||
|
||||
@dataclass
|
||||
class PrivacyBudget:
|
||||
"""Budget to bound data sharing and protect privacy in federation."""
|
||||
enabled: bool = True
|
||||
allowed_signals: List[str] = field(default_factory=list)
|
||||
total_budget_units: float = 1.0 # abstract budget units
|
||||
per_signal_budget: Dict[str, float] = field(default_factory=dict)
|
||||
timestamp: float = field(default_factory=time.time)
|
||||
|
||||
def use(self, signal: str, amount: float) -> None:
|
||||
# Simple budgeting semantics: deduct amount from per-signal budget
|
||||
current = self.per_signal_budget.get(signal, self.total_budget_units)
|
||||
self.per_signal_budget[signal] = max(0.0, current - amount)
|
||||
self.timestamp = time.time()
|
||||
|
||||
|
||||
__all__ = [
|
||||
"LocalProblem",
|
||||
"SharedVariables",
|
||||
|
|
@ -74,4 +108,6 @@ __all__ = [
|
|||
"DualVariables",
|
||||
"AuditLog",
|
||||
"GraphOfContracts",
|
||||
"SafetyBudget",
|
||||
"PrivacyBudget",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
from energiamesh.core import SafetyBudget, PrivacyBudget
|
||||
|
||||
|
||||
def test_safety_budget_basic():
|
||||
sb = SafetyBudget(enabled=True, max_current_draw_a=50.0, max_voltage_variation_pu=0.02)
|
||||
assert sb.enabled is True
|
||||
assert sb.max_current_draw_a == 50.0
|
||||
assert sb.max_voltage_variation_pu == 0.02
|
||||
# Update device limits
|
||||
sb.update("DER-01", 40.0)
|
||||
assert sb.device_limits["DER-01"] == 40.0
|
||||
|
||||
|
||||
def test_privacy_budget_basic_and_use():
|
||||
pb = PrivacyBudget(enabled=True, allowed_signals=["forecast"], total_budget_units=1.0)
|
||||
assert pb.enabled is True
|
||||
assert pb.allowed_signals == ["forecast"]
|
||||
pb.per_signal_budget["forecast"] = 1.0
|
||||
pb.use("forecast", 0.25)
|
||||
assert pb.per_signal_budget["forecast"] == 0.75
|
||||
Loading…
Reference in New Issue