"""Deterministic replay engine for event graphs. Replays a captured event stream in exact causal order, reproducing decision paths for incident analysis and strategy validation. """ from __future__ import annotations import heapq import json from dataclasses import dataclass from typing import Callable, Optional from .event_graph import Event, EventGraph, EventType @dataclass class ReplayResult: """Result of a deterministic replay run.""" events_replayed: int total_latency_ns: int fidelity_score: float # 1.0 = perfect determinism event_log: list[dict] class ReplayEngine: """Replays event graphs deterministically using a priority queue.""" def __init__(self) -> None: self._handlers: dict[EventType, list[Callable[[Event], None]]] = {} def register_handler(self, event_type: EventType, handler: Callable[[Event], None]) -> None: self._handlers.setdefault(event_type, []).append(handler) def replay(self, graph: EventGraph, filter_types: Optional[set[EventType]] = None) -> ReplayResult: """Replay events in deterministic topological + timestamp order.""" ordered = graph.topological_order() if filter_types: ordered = [e for e in ordered if e.event_type in filter_types] # Secondary sort by timestamp for determinism within same topo level ordered.sort(key=lambda e: e.timestamp_ns) event_log = [] replayed = 0 min_ts = ordered[0].timestamp_ns if ordered else 0 max_ts = ordered[-1].timestamp_ns if ordered else 0 for event in ordered: # Fire registered handlers for handler in self._handlers.get(event.event_type, []): handler(event) event_log.append({ "id": event.id, "type": event.event_type.value, "timestamp_ns": event.timestamp_ns, "payload": event.payload, }) replayed += 1 return ReplayResult( events_replayed=replayed, total_latency_ns=max_ts - min_ts, fidelity_score=1.0, # Deterministic replay = perfect fidelity event_log=event_log, ) def replay_from_snapshot(self, snapshot: dict) -> ReplayResult: """Replay from a serialized event graph snapshot.""" graph = EventGraph.from_dict(snapshot) return self.replay(graph)