build(agent): semicolon#54de0b iteration
This commit is contained in:
parent
6cbbbce9cb
commit
5981186d1c
|
|
@ -1,42 +1,34 @@
|
|||
"""GridResilience Studio core package (minimal bootstrap).
|
||||
"""GridResilience Studio public package."""
|
||||
|
||||
This repository adds a production-oriented, offline-first cross-domain orchestrator
|
||||
foundation. This bootstrap provides a starting point for the EnergiBridge canonical
|
||||
interoperability layer and related primitives used across adapters.
|
||||
from .bridge import EnergiBridge
|
||||
from .core import (
|
||||
AuditLog,
|
||||
DeltaStore,
|
||||
DualVariables,
|
||||
Morphism,
|
||||
Object,
|
||||
PlanDelta,
|
||||
PrivacyBudget,
|
||||
RegistryEntry,
|
||||
build_sample_world,
|
||||
)
|
||||
from .governance import GovernanceEntry, GovernanceLedger
|
||||
from .offline_sync import DeltaSyncEngine
|
||||
from .registry import GraphRegistry
|
||||
|
||||
Note: This module also patches on import to ensure a consistent API surface across
|
||||
environments where the installed distribution might differ from the in-repo sources.
|
||||
"""
|
||||
|
||||
# Lightweight runtime patch to ensure EnergiBridge API surface is consistent even if
|
||||
# an installed distribution lacks the wrappers we rely on during tests.
|
||||
try:
|
||||
from . import bridge as _bridge # type: ignore
|
||||
EnergiBridge = getattr(_bridge, "EnergiBridge", None)
|
||||
if EnergiBridge is not None:
|
||||
# Add missing direct API wrappers if they are not present
|
||||
if not hasattr(EnergiBridge, "map_local_problem"):
|
||||
def _map_local_problem(self, local_problem):
|
||||
return {"type": "Objects", "local_problem": local_problem}
|
||||
EnergiBridge.map_local_problem = _map_local_problem # type: ignore
|
||||
if not hasattr(EnergiBridge, "map_shared_signals"):
|
||||
def _map_shared_signals(self, shared_signals):
|
||||
return {"type": "Morphisms", "shared_signals": shared_signals}
|
||||
EnergiBridge.map_shared_signals = _map_shared_signals # type: ignore
|
||||
if not hasattr(EnergiBridge, "map_plan_delta"):
|
||||
def _map_plan_delta(self, plan_delta):
|
||||
return {"type": "PlanDelta", "delta": plan_delta}
|
||||
EnergiBridge.map_plan_delta = _map_plan_delta # type: ignore
|
||||
if not hasattr(EnergiBridge, "register_adapter"):
|
||||
def _register_adapter(self, adapter_id, contract_version, data_contract):
|
||||
entry = {
|
||||
"adapter_id": adapter_id,
|
||||
"contract_version": contract_version,
|
||||
"data_contract": data_contract,
|
||||
}
|
||||
self._registry[adapter_id] = entry
|
||||
return entry
|
||||
EnergiBridge.register_adapter = _register_adapter # type: ignore
|
||||
except Exception:
|
||||
# Be permissive in patching; if anything goes wrong, tests should still run
|
||||
pass
|
||||
__all__ = [
|
||||
"Object",
|
||||
"Morphism",
|
||||
"PlanDelta",
|
||||
"DualVariables",
|
||||
"AuditLog",
|
||||
"PrivacyBudget",
|
||||
"RegistryEntry",
|
||||
"DeltaStore",
|
||||
"build_sample_world",
|
||||
"DeltaSyncEngine",
|
||||
"GraphRegistry",
|
||||
"GovernanceEntry",
|
||||
"GovernanceLedger",
|
||||
"EnergiBridge",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, List
|
||||
|
||||
|
||||
@dataclass
|
||||
class Object:
|
||||
"""Canonical object describing a device or asset."""
|
||||
|
||||
id: str
|
||||
type: str
|
||||
properties: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if not self.id:
|
||||
raise ValueError("Object requires an id")
|
||||
|
||||
|
||||
@dataclass
|
||||
class Morphism:
|
||||
"""Canonical morphism describing a versioned signal edge."""
|
||||
|
||||
id: str
|
||||
source: str
|
||||
target: str
|
||||
signals: Dict[str, Any] = field(default_factory=dict)
|
||||
version: int = 0
|
||||
|
||||
def bump(self) -> None:
|
||||
self.version += 1
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlanDelta:
|
||||
"""Incremental islanding or load-shedding update."""
|
||||
|
||||
delta_id: str
|
||||
islanded: bool = False
|
||||
actions: List[Dict[str, Any]] = field(default_factory=list)
|
||||
tags: Dict[str, str] = field(default_factory=dict)
|
||||
|
||||
def add_action(self, action: Dict[str, Any]) -> None:
|
||||
self.actions.append(action)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DualVariables:
|
||||
id: str
|
||||
price_vector: List[float] = field(default_factory=list)
|
||||
feasibility: float = 0.0
|
||||
version: int = 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class AuditLog:
|
||||
entry: str
|
||||
signer: str
|
||||
timestamp: str
|
||||
contract_id: str
|
||||
version: int = 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class PrivacyBudget:
|
||||
signal: str
|
||||
budget: float
|
||||
remaining: float
|
||||
expiry: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class RegistryEntry:
|
||||
adapter_id: str
|
||||
contract_version: str
|
||||
data_contract: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
class DeltaStore:
|
||||
def __init__(self) -> None:
|
||||
self.objects: Dict[str, Object] = {}
|
||||
self.morphisms: Dict[str, Morphism] = {}
|
||||
self.deltas: List[PlanDelta] = []
|
||||
|
||||
def add_object(self, obj: Object) -> None:
|
||||
self.objects[obj.id] = obj
|
||||
|
||||
def add_morphism(self, morph: Morphism) -> None:
|
||||
self.morphisms[morph.id] = morph
|
||||
|
||||
def add_delta(self, delta: PlanDelta) -> None:
|
||||
self.deltas.append(delta)
|
||||
|
||||
|
||||
def build_sample_world() -> DeltaStore:
|
||||
ds = DeltaStore()
|
||||
ds.add_object(Object(id="DER1", type="DER", properties={"rated_kW": 500, "location": "SiteA"}))
|
||||
ds.add_object(Object(id="LOAD1", type="Load", properties={"critical": True, "rating_kW": 150}))
|
||||
ds.add_morphism(Morphism(id="SIG1", source="DER1", target="LOAD1", signals={"voltage": 1.0}, version=1))
|
||||
ds.add_delta(PlanDelta(delta_id="DELTA1", islanded=True, actions=[{"type": "island", "target": "LOAD1"}], tags={"sig": "v1"}))
|
||||
return ds
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclass
|
||||
class GovernanceEntry:
|
||||
contract_id: str
|
||||
action: str
|
||||
signer: str
|
||||
timestamp: str
|
||||
version: int
|
||||
payload_hash: str | None = None
|
||||
|
||||
|
||||
class GovernanceLedger:
|
||||
def __init__(self) -> None:
|
||||
self._entries: List[GovernanceEntry] = []
|
||||
self._last_hash: str | None = None
|
||||
|
||||
def _hash_entry(self, entry: GovernanceEntry) -> str:
|
||||
data = {
|
||||
"contract_id": entry.contract_id,
|
||||
"action": entry.action,
|
||||
"signer": entry.signer,
|
||||
"timestamp": entry.timestamp,
|
||||
"version": entry.version,
|
||||
"payload_hash": entry.payload_hash,
|
||||
"prev_hash": self._last_hash,
|
||||
}
|
||||
return hashlib.sha256(json.dumps(data, sort_keys=True).encode("utf-8")).hexdigest()
|
||||
|
||||
def append(self, contract_id: str, action: str, signer: str, version: int, payload_hash: str | None = None) -> GovernanceEntry:
|
||||
entry = GovernanceEntry(
|
||||
contract_id=contract_id,
|
||||
action=action,
|
||||
signer=signer,
|
||||
timestamp=datetime.utcnow().isoformat() + "Z",
|
||||
version=version,
|
||||
payload_hash=payload_hash,
|
||||
)
|
||||
self._entries.append(entry)
|
||||
self._last_hash = self._hash_entry(entry)
|
||||
return entry
|
||||
|
||||
def entries(self) -> List[GovernanceEntry]:
|
||||
return list(self._entries)
|
||||
|
||||
def latest_hash(self) -> str | None:
|
||||
return self._last_hash
|
||||
|
||||
|
||||
__all__ = ["GovernanceLedger", "GovernanceEntry"]
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import List, Tuple
|
||||
|
||||
from .core import DeltaStore, Morphism, Object, PlanDelta
|
||||
|
||||
|
||||
class DeltaSyncEngine:
|
||||
"""Lightweight offline-first delta-sync engine."""
|
||||
|
||||
def __init__(self, store: DeltaStore | None = None) -> None:
|
||||
self.store = store or DeltaStore()
|
||||
self.remote_version = 0
|
||||
self.local_version = 0
|
||||
|
||||
def apply_delta(self, delta: PlanDelta) -> None:
|
||||
if any(existing.delta_id == delta.delta_id for existing in self.store.deltas):
|
||||
return
|
||||
self.store.add_delta(delta)
|
||||
self.local_version += 1
|
||||
|
||||
def snapshot(self) -> List[PlanDelta]:
|
||||
return list(self.store.deltas)
|
||||
|
||||
def delta_with_cipher(self, delta: PlanDelta) -> Tuple[PlanDelta, str]:
|
||||
delta.tags["hash"] = f"hash-{delta.delta_id}-{self.local_version}"
|
||||
return delta, delta.tags["hash"]
|
||||
|
||||
|
||||
__all__ = ["DeltaSyncEngine", "DeltaStore", "Object", "Morphism", "PlanDelta"]
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class RegistryEntry:
|
||||
adapter_id: str
|
||||
contract_version: str
|
||||
data_contract: Dict[str, Any] = field(default_factory=dict)
|
||||
metadata: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
class GraphRegistry:
|
||||
def __init__(self) -> None:
|
||||
self._entries: Dict[str, RegistryEntry] = {}
|
||||
|
||||
def add_entry(self, entry: RegistryEntry) -> None:
|
||||
self._entries[entry.adapter_id] = entry
|
||||
|
||||
def get_entry(self, adapter_id: str) -> Optional[RegistryEntry]:
|
||||
return self._entries.get(adapter_id)
|
||||
|
||||
def list_entries(self) -> Dict[str, RegistryEntry]:
|
||||
return dict(self._entries)
|
||||
|
||||
|
||||
__all__ = ["GraphRegistry", "RegistryEntry"]
|
||||
Loading…
Reference in New Issue