cortex-runtime 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. cortex/__init__.py +51 -0
  2. cortex/__main__.py +13 -0
  3. cortex/client.py +263 -0
  4. cortex/compat.py +20 -0
  5. cortex/exceptions.py +57 -0
  6. cortex/plugin.py +50 -0
  7. cortex/py.typed +1 -0
  8. cortex/schema/__init__.py +29 -0
  9. cortex/schema/events.py +127 -0
  10. cortex/tools/__init__.py +3 -0
  11. cortex/tools/cli/__init__.py +3 -0
  12. cortex/tools/cli/main.py +139 -0
  13. cortex/tools/cli/runner.py +94 -0
  14. cortex/tools/cli/scaffolder.py +109 -0
  15. cortex/tools/gen_test_bin.py +35 -0
  16. cortex/tools/kernel/__init__.py +3 -0
  17. cortex/tools/kernel/actors/__init__.py +3 -0
  18. cortex/tools/kernel/actors/executor.py +44 -0
  19. cortex/tools/kernel/actors/planner.py +38 -0
  20. cortex/tools/kernel/context.py +22 -0
  21. cortex/tools/kernel/drivers/__init__.py +3 -0
  22. cortex/tools/kernel/drivers/mock_robot.py +84 -0
  23. cortex/tools/kernel/drivers/rtl_verilator.py +49 -0
  24. cortex/tools/kernel/graph/__init__.py +3 -0
  25. cortex/tools/kernel/graph/analyzer.py +52 -0
  26. cortex/tools/kernel/graph/execution_graph.py +44 -0
  27. cortex/tools/kernel/mailbox.py +35 -0
  28. cortex/tools/kernel/plugin/__init__.py +3 -0
  29. cortex/tools/kernel/plugin/loader.py +87 -0
  30. cortex/tools/kernel/plugin/manifest.py +53 -0
  31. cortex/tools/kernel/registry.py +36 -0
  32. cortex/tools/kernel/schema/__init__.py +3 -0
  33. cortex/tools/kernel/schema/contract.py +16 -0
  34. cortex/tools/kernel/schema/event.py +54 -0
  35. cortex/tools/kernel/schema/message.py +105 -0
  36. cortex/tools/kernel/schema/workflow.py +38 -0
  37. cortex/tools/kernel/services/__init__.py +3 -0
  38. cortex/tools/kernel/services/event_store.py +25 -0
  39. cortex/tools/kernel/services/execution_intelligence.py +49 -0
  40. cortex/tools/kernel/services/graph_builder.py +81 -0
  41. cortex/tools/kernel/services/replay.py +50 -0
  42. cortex/tools/kernel/services/verification.py +85 -0
  43. cortex/tools/kernel/transport.py +50 -0
  44. cortex/tools/run_phase2_verification.sh +20 -0
  45. cortex/tools/verification/__init__.py +5 -0
  46. cortex/tools/verification/adapters/__init__.py +3 -0
  47. cortex/tools/verification/adapters/base.py +14 -0
  48. cortex/tools/verification/adapters/coq.py +73 -0
  49. cortex/tools/verification/adapters/rtl.py +77 -0
  50. cortex/tools/verification/adapters/rust.py +72 -0
  51. cortex/tools/verification/archive.py +58 -0
  52. cortex/tools/verification/bus.py +28 -0
  53. cortex/tools/verification/contract.py +70 -0
  54. cortex/tools/verification/engine.py +121 -0
  55. cortex/tools/verification/generator/__init__.py +3 -0
  56. cortex/tools/verification/generator/composer.py +36 -0
  57. cortex/tools/verification/generator/program.py +46 -0
  58. cortex/tools/verification/generator/state.py +54 -0
  59. cortex/tools/verification/invariants/__init__.py +3 -0
  60. cortex/tools/verification/invariants/capability.py +62 -0
  61. cortex/tools/verification/metrics/__init__.py +3 -0
  62. cortex/tools/verification/metrics/base.py +18 -0
  63. cortex/tools/verification/metrics/opcode.py +25 -0
  64. cortex/tools/verification/metrics/state_space.py +26 -0
  65. cortex/tools/verification/metrics/trap.py +26 -0
  66. cortex/tools/verification/mutation.py +48 -0
  67. cortex/tools/verification/oracle.py +164 -0
  68. cortex/tools/verification/schema/__init__.py +44 -0
  69. cortex/tools/verification/schema/event.py +44 -0
  70. cortex/tools/verification/shrink.py +26 -0
  71. cortex/tools/verify.py +64 -0
  72. cortex_runtime-0.2.0.dist-info/METADATA +220 -0
  73. cortex_runtime-0.2.0.dist-info/RECORD +76 -0
  74. cortex_runtime-0.2.0.dist-info/WHEEL +4 -0
  75. cortex_runtime-0.2.0.dist-info/entry_points.txt +2 -0
  76. cortex_runtime-0.2.0.dist-info/licenses/LICENSE +201 -0
cortex/__init__.py ADDED
@@ -0,0 +1,51 @@
1
+ """
2
+ Cortex Platform Public API Package
3
+
4
+ Provides vendor-neutral, technology-neutral semantic execution layer,
5
+ workflow boundary management, sandboxed capability negotiation, and verification.
6
+ """
7
+
8
+ from cortex.client import CortexClient
9
+ from cortex.exceptions import (
10
+ CapabilityViolationError,
11
+ CortexError,
12
+ ManifestError,
13
+ WorkflowExecutionError,
14
+ )
15
+ from cortex.plugin import BasePlugin, Capability, PluginContext, PluginManifest
16
+ from cortex.schema import (
17
+ BaseEvent,
18
+ CommandIssuedEvent,
19
+ DriverTelemetryEvent,
20
+ IntentEvent,
21
+ PlanGeneratedEvent,
22
+ TelemetryEvent,
23
+ VerificationResultEvent,
24
+ Workflow,
25
+ WorkflowPolicy,
26
+ WorkflowState,
27
+ )
28
+ from cortex.tools.kernel.services.event_store import EventStoreService as EventStore
29
+
30
+ __all__ = [
31
+ "BaseEvent",
32
+ "BasePlugin",
33
+ "Capability",
34
+ "CapabilityViolationError",
35
+ "CommandIssuedEvent",
36
+ "CortexClient",
37
+ "CortexError",
38
+ "DriverTelemetryEvent",
39
+ "EventStore",
40
+ "IntentEvent",
41
+ "ManifestError",
42
+ "PlanGeneratedEvent",
43
+ "PluginContext",
44
+ "PluginManifest",
45
+ "TelemetryEvent",
46
+ "VerificationResultEvent",
47
+ "Workflow",
48
+ "WorkflowExecutionError",
49
+ "WorkflowPolicy",
50
+ "WorkflowState",
51
+ ]
cortex/__main__.py ADDED
@@ -0,0 +1,13 @@
1
+ """
2
+ Cortex Platform CLI Execution Entrypoint
3
+
4
+ Enables executing the Cortex Developer CLI directly via Python module dispatch:
5
+ python3 -m cortex <command> [options]
6
+ """
7
+
8
+ import sys
9
+
10
+ from cortex.tools.cli.main import main
11
+
12
+ if __name__ == "__main__":
13
+ sys.exit(main())
cortex/client.py ADDED
@@ -0,0 +1,263 @@
1
+ """
2
+ Public CortexClient API
3
+
4
+ Main developer-facing entrypoint for orchestrating workflows, registering plugins,
5
+ enforcing capability sandboxes, inspecting traces, and executing deterministic replay.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ from typing import cast
11
+
12
+ from cortex.plugin import BasePlugin, PluginContext
13
+ from cortex.schema.events import (
14
+ BaseEvent,
15
+ IntentEvent,
16
+ VerificationResultEvent,
17
+ Workflow,
18
+ WorkflowPolicy,
19
+ WorkflowState,
20
+ dict_to_event,
21
+ event_to_dict,
22
+ )
23
+ from cortex.tools.kernel.graph.analyzer import ExecutionGraphAnalyzer
24
+ from cortex.tools.kernel.plugin.loader import (
25
+ PluginRegistration,
26
+ PluginRegistry,
27
+ PluginState,
28
+ )
29
+ from cortex.tools.kernel.services.event_store import EventStoreService
30
+ from cortex.tools.kernel.services.graph_builder import ExecutionGraphBuilderService
31
+ from cortex.tools.kernel.services.replay import DeterministicReplayEngine
32
+ from cortex.tools.kernel.transport import AnyEvent, EventHandler, InMemoryTransport
33
+
34
+
35
+ class CortexClient:
36
+ """Public high-level Python API for Cortex execution runtime."""
37
+
38
+ platform_capabilities: set[str]
39
+ registry: PluginRegistry
40
+ transport: InMemoryTransport
41
+ event_store: EventStoreService
42
+ graph_builder: ExecutionGraphBuilderService
43
+ registered_plugins: list[BasePlugin]
44
+
45
+ def __init__(self, platform_capabilities: set[str] | None = None) -> None:
46
+ if platform_capabilities is None:
47
+ # Default standard platform capabilities
48
+ self.platform_capabilities = {
49
+ "workflow.plan.create",
50
+ "workflow.command.issue",
51
+ "hardware.telemetry.read",
52
+ "verification.oracle.execute",
53
+ "verification.invariant.check",
54
+ "fs:read",
55
+ "exec:git",
56
+ "exec:pytest",
57
+ }
58
+ else:
59
+ self.platform_capabilities = set(platform_capabilities)
60
+
61
+ self.registry = PluginRegistry(self.platform_capabilities)
62
+ self.transport = InMemoryTransport()
63
+ self.event_store = EventStoreService()
64
+ self.graph_builder = ExecutionGraphBuilderService()
65
+ self.registered_plugins = []
66
+
67
+ # Wire global stores using named def handlers to satisfy lint & type checkers
68
+ def store_handler(e: AnyEvent) -> None:
69
+ self.event_store.record_event(e)
70
+
71
+ def builder_handler(e: AnyEvent) -> None:
72
+ self.graph_builder.record_message(e)
73
+
74
+ self.transport.subscribe(BaseEvent, store_handler)
75
+ self.transport.subscribe(BaseEvent, builder_handler)
76
+
77
+ def register_plugin(self, plugin: BasePlugin) -> PluginRegistration:
78
+ """Register a plugin with capability negotiation."""
79
+ registration = self.registry.register(plugin.manifest)
80
+ if registration.state == PluginState.ACTIVE:
81
+ context = PluginContext(
82
+ session_id="default_session",
83
+ granted_capabilities=registration.granted_capabilities,
84
+ publish_func=self.transport.publish,
85
+ )
86
+ plugin.set_context(context)
87
+
88
+ def create_plugin_handler(p: BasePlugin) -> EventHandler:
89
+ def plugin_handler(e: AnyEvent) -> None:
90
+ self._dispatch_to_plugin(p, e)
91
+ return plugin_handler
92
+
93
+ for _ in plugin.manifest.consumes_events:
94
+ self.transport.subscribe(BaseEvent, create_plugin_handler(plugin))
95
+
96
+ self.registered_plugins.append(plugin)
97
+ return registration
98
+
99
+ def _dispatch_to_plugin(self, plugin: BasePlugin, event: AnyEvent) -> None:
100
+ """Helper to safely dispatch event to plugin if active and consuming."""
101
+ if plugin.context and isinstance(event, BaseEvent) and type(event).__name__ in plugin.manifest.consumes_events:
102
+ plugin.on_event(event)
103
+
104
+ def create_workflow(self, name: str, goal: str, policy: WorkflowPolicy | None = None) -> Workflow:
105
+ """Instantiate a new Workflow primitive."""
106
+ if policy is None:
107
+ policy = WorkflowPolicy()
108
+ return Workflow(name=name, goal=goal, policy=policy)
109
+
110
+ def run_workflow(self, workflow: Workflow, initial_intent: IntentEvent | None = None) -> Workflow:
111
+ """Executes a workflow from PENDING to RUNNING to COMPLETED or FAILED."""
112
+ workflow.state = WorkflowState.RUNNING
113
+
114
+ # Verify whether any registered plugin was REJECTED during negotiation
115
+ rejected = self.registry.get_rejected_plugins()
116
+ if rejected:
117
+ denied_caps: list[str] = []
118
+ for r in rejected:
119
+ denied_caps.extend(r.denied_capabilities)
120
+
121
+ violation_event = VerificationResultEvent(
122
+ workflow_id=workflow.workflow_id,
123
+ passed=False,
124
+ rule_id="CAPABILITY_VIOLATION",
125
+ details={
126
+ "reason": f"Plugins rejected due to unauthorized capabilities: {denied_caps}",
127
+ "rejected_plugins": [r.manifest.name for r in rejected],
128
+ },
129
+ )
130
+ self.transport.publish(violation_event)
131
+ workflow.state = WorkflowState.FAILED
132
+ return workflow
133
+
134
+ if initial_intent is None:
135
+ initial_intent = IntentEvent(workflow_id=workflow.workflow_id, goal=workflow.goal)
136
+
137
+ self.transport.publish(initial_intent)
138
+
139
+ # Check for any failed verification events in store
140
+ failed_verifications = [
141
+ e for e in self.event_store.get_log()
142
+ if isinstance(e, VerificationResultEvent) and not e.passed
143
+ ]
144
+
145
+ if failed_verifications:
146
+ workflow.state = WorkflowState.FAILED
147
+ else:
148
+ workflow.state = WorkflowState.COMPLETED
149
+
150
+ return workflow
151
+
152
+ def inspect_workflow(self, trace_or_id: str) -> dict[str, str | int | list[str] | list[dict[str, object]]]:
153
+ """Inspects an execution trace and provides graph lineage and root cause analysis."""
154
+ events = self._resolve_events(trace_or_id)
155
+
156
+ builder = ExecutionGraphBuilderService()
157
+ for e in events:
158
+ builder.record_message(e)
159
+
160
+ graph = list(builder.graphs.values())[0] if builder.graphs else None
161
+
162
+ failed_nodes: list[dict[str, object]] = []
163
+ causality_tree: list[str] = []
164
+ wf_name = "Inspected Workflow"
165
+ wf_goal = "Trace Inspection"
166
+
167
+ if os.path.exists(trace_or_id):
168
+ with open(trace_or_id, "r", encoding="utf-8") as f:
169
+ raw_data = cast(object, json.load(f))
170
+ if isinstance(raw_data, dict):
171
+ data = cast(dict[str, object], raw_data)
172
+ wf_name = str(data.get("name", wf_name))
173
+ wf_goal = str(data.get("goal", wf_goal))
174
+
175
+ if graph:
176
+ analyzer = ExecutionGraphAnalyzer(graph)
177
+ for node in analyzer.find_failed_nodes():
178
+ failed_nodes.append({
179
+ "id": node.node_id,
180
+ "type": node.node_type,
181
+ "payload": node.payload,
182
+ "parent_id": node.parent_id,
183
+ })
184
+
185
+ for node_id, node in graph.nodes.items():
186
+ parent_info = f" -> parent: {node.parent_id[:8]}" if node.parent_id else " (ROOT)"
187
+ causality_tree.append(f"[{node.node_type}] ID: {node_id[:8]}{parent_info} | {node.payload}")
188
+
189
+ return {
190
+ "name": wf_name,
191
+ "goal": wf_goal,
192
+ "total_events": len(events),
193
+ "node_count": len(graph.nodes) if graph else 0,
194
+ "failed_nodes": failed_nodes,
195
+ "causality_tree": causality_tree,
196
+ }
197
+
198
+ def replay_workflow(self, trace_or_id: str) -> dict[str, str | int | bool]:
199
+ """Replays an event journal and asserts 100% causal sequence immutability."""
200
+ events = self._resolve_events(trace_or_id)
201
+
202
+ replay_transport = InMemoryTransport()
203
+ replayed_events: list[BaseEvent] = []
204
+
205
+ def replay_handler(e: AnyEvent) -> None:
206
+ if isinstance(e, BaseEvent):
207
+ replayed_events.append(e)
208
+
209
+ replay_transport.subscribe(BaseEvent, replay_handler)
210
+
211
+ engine = DeterministicReplayEngine(replay_transport)
212
+ count = engine.replay_journal(events)
213
+ result = engine.verify_replayed_lineage(events, replayed_events)
214
+
215
+ return {
216
+ "replayed_count": count,
217
+ "deterministic": cast(bool, result.get("match", False)),
218
+ "reason": cast(str, result.get("reason", "")),
219
+ }
220
+
221
+ def save_trace(self, workflow_id: str, filepath: str, name: str = "Workflow", goal: str = "Execution") -> str:
222
+ """Saves current event store log to JSON file."""
223
+ events = self.event_store.get_log()
224
+ serialized: list[dict[str, object]] = []
225
+ for e in events:
226
+ if isinstance(e, BaseEvent):
227
+ serialized.append(event_to_dict(e))
228
+
229
+ payload: dict[str, object] = {
230
+ "name": name,
231
+ "goal": goal,
232
+ "workflow_id": workflow_id,
233
+ "event_count": len(serialized),
234
+ "events": serialized,
235
+ }
236
+
237
+ os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
238
+ with open(filepath, "w", encoding="utf-8") as f:
239
+ json.dump(payload, f, indent=2)
240
+
241
+ return filepath
242
+
243
+ def _resolve_events(self, trace_or_id: str) -> list[BaseEvent]:
244
+ """Resolves file path or in-memory event log."""
245
+ if os.path.exists(trace_or_id):
246
+ with open(trace_or_id, "r", encoding="utf-8") as f:
247
+ raw_data = cast(object, json.load(f))
248
+ if isinstance(raw_data, dict):
249
+ data = cast(dict[str, object], raw_data)
250
+ raw_events: object = data.get("events", [])
251
+ if isinstance(raw_events, list):
252
+ events_list = cast(list[object], raw_events)
253
+ events_dict_list: list[dict[str, object]] = [
254
+ cast(dict[str, object], item) for item in events_list if isinstance(item, dict)
255
+ ]
256
+ return [dict_to_event(e) for e in events_dict_list]
257
+
258
+ cortex_path = os.path.join(os.getcwd(), ".cortex", "events", f"{trace_or_id}.json")
259
+ if os.path.exists(cortex_path):
260
+ return self._resolve_events(cortex_path)
261
+
262
+ # Fallback to current in-memory log
263
+ return [e for e in self.event_store.get_log() if isinstance(e, BaseEvent)]
cortex/compat.py ADDED
@@ -0,0 +1,20 @@
1
+ """
2
+ Zero-dependency compatibility helpers for Python 3.10+
3
+ """
4
+
5
+ from collections.abc import Callable
6
+ from typing import TypeVar
7
+
8
+ F = TypeVar("F", bound=Callable[..., object])
9
+
10
+ try:
11
+ from typing import override as override # type: ignore[attr-defined]
12
+ except ImportError:
13
+ try:
14
+ from typing_extensions import override as override # type: ignore[no-redef]
15
+ except ImportError:
16
+ def override(method: F, /) -> F: # type: ignore[no-redef]
17
+ return method
18
+
19
+
20
+ __all__ = ["override"]
cortex/exceptions.py ADDED
@@ -0,0 +1,57 @@
1
+ """
2
+ Custom Exceptions for Cortex Platform
3
+ """
4
+
5
+
6
+ from cortex.compat import override
7
+
8
+
9
+ class CortexError(Exception):
10
+ """Base exception class for all Cortex framework runtime errors."""
11
+
12
+ message: str
13
+ exit_code: int
14
+
15
+ def __init__(self, message: str, exit_code: int = 1):
16
+ super().__init__(message)
17
+ self.message = message
18
+ self.exit_code = exit_code
19
+
20
+ @override
21
+ def __str__(self) -> str:
22
+ return self.message
23
+
24
+
25
+ class WorkflowExecutionError(CortexError):
26
+ """Raised when a workflow fails during execution or policy evaluation."""
27
+
28
+ workflow_id: str | None
29
+
30
+ def __init__(self, message: str, workflow_id: str | None = None):
31
+ super().__init__(message, exit_code=1)
32
+ self.workflow_id = workflow_id
33
+
34
+
35
+ class CapabilityViolationError(CortexError):
36
+ """Raised when a plugin attempts an unauthorized action exceeding its granted capabilities."""
37
+
38
+ capability: str | None
39
+
40
+ def __init__(self, message: str, capability: str | None = None):
41
+ super().__init__(message, exit_code=2)
42
+ self.capability = capability
43
+
44
+
45
+ class ManifestError(CortexError):
46
+ """Raised when a plugin manifest schema or definition is invalid."""
47
+
48
+ def __init__(self, message: str):
49
+ super().__init__(message, exit_code=3)
50
+
51
+
52
+ __all__ = [
53
+ "CapabilityViolationError",
54
+ "CortexError",
55
+ "ManifestError",
56
+ "WorkflowExecutionError",
57
+ ]
cortex/plugin.py ADDED
@@ -0,0 +1,50 @@
1
+ """
2
+ Public Plugin Interface & Capability Management for Cortex Platform
3
+ """
4
+
5
+ from abc import ABC, abstractmethod
6
+ from collections.abc import Callable
7
+ from dataclasses import dataclass
8
+
9
+ from cortex.schema.events import BaseEvent
10
+ from cortex.tools.kernel.plugin.manifest import PluginManifest
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class Capability:
15
+ """Public capability representation for permission grants."""
16
+ name: str
17
+
18
+
19
+ @dataclass
20
+ class PluginContext:
21
+ """Runtime context provided to plugins, scoped strictly to granted capabilities."""
22
+ session_id: str
23
+ granted_capabilities: set[str]
24
+ publish_func: Callable[[BaseEvent], None]
25
+
26
+ def publish(self, event: BaseEvent) -> None:
27
+ """Publish an event to the runtime event bus."""
28
+ self.publish_func(event)
29
+
30
+ def has_capability(self, cap_name: str) -> bool:
31
+ """Check if a capability was granted to this plugin instance."""
32
+ return cap_name in self.granted_capabilities
33
+
34
+
35
+ class BasePlugin(ABC):
36
+ """Abstract Base Class for all external Cortex plugins."""
37
+ manifest: PluginManifest
38
+ context: PluginContext | None
39
+
40
+ def __init__(self, manifest: PluginManifest):
41
+ self.manifest = manifest
42
+ self.context = None
43
+
44
+ def set_context(self, context: PluginContext) -> None:
45
+ """Attach runtime context after capability negotiation."""
46
+ self.context = context
47
+
48
+ @abstractmethod
49
+ def on_event(self, event: BaseEvent) -> None:
50
+ """Handle incoming events matching the plugin's consumed event contracts."""
cortex/py.typed ADDED
@@ -0,0 +1 @@
1
+ # Marker file for PEP 561.
@@ -0,0 +1,29 @@
1
+ """
2
+ Public Cortex Schemas & Events Package
3
+ """
4
+
5
+ from cortex.schema.events import (
6
+ BaseEvent,
7
+ CommandIssuedEvent,
8
+ DriverTelemetryEvent,
9
+ IntentEvent,
10
+ PlanGeneratedEvent,
11
+ TelemetryEvent,
12
+ VerificationResultEvent,
13
+ Workflow,
14
+ WorkflowPolicy,
15
+ WorkflowState,
16
+ )
17
+
18
+ __all__ = [
19
+ "BaseEvent",
20
+ "CommandIssuedEvent",
21
+ "DriverTelemetryEvent",
22
+ "IntentEvent",
23
+ "PlanGeneratedEvent",
24
+ "TelemetryEvent",
25
+ "VerificationResultEvent",
26
+ "Workflow",
27
+ "WorkflowPolicy",
28
+ "WorkflowState",
29
+ ]
@@ -0,0 +1,127 @@
1
+ """
2
+ Public Event and Schema Exports for Cortex Platform
3
+ """
4
+
5
+ from dataclasses import asdict
6
+ from typing import cast
7
+
8
+ from cortex.tools.kernel.schema.message import (
9
+ BaseEvent,
10
+ CommandIssuedEvent,
11
+ DriverTelemetryEvent,
12
+ IntentEvent,
13
+ PlanGeneratedEvent,
14
+ VerificationResultEvent,
15
+ )
16
+ from cortex.tools.kernel.schema.workflow import Workflow, WorkflowPolicy, WorkflowState
17
+
18
+ # Public Alias
19
+ TelemetryEvent = DriverTelemetryEvent
20
+
21
+
22
+ def event_to_dict(event: BaseEvent) -> dict[str, object]:
23
+ """Serialize BaseEvent subclass to typed JSON-compatible dictionary."""
24
+ d = cast(dict[str, object], asdict(event))
25
+ d["_event_type"] = type(event).__name__
26
+ return d
27
+
28
+
29
+ def dict_to_event(d: dict[str, object]) -> BaseEvent:
30
+ """Deserialize JSON dictionary to corresponding BaseEvent subclass."""
31
+ d_copy = dict(d)
32
+ event_type = str(d_copy.pop("_event_type", "BaseEvent"))
33
+
34
+ match event_type:
35
+ case "IntentEvent":
36
+ return IntentEvent(
37
+ workflow_id=cast(str | None, d_copy.get("workflow_id")),
38
+ goal=str(d_copy.get("goal", "")),
39
+ parameters=cast(dict[str, object], d_copy.get("parameters", {})),
40
+ intent_id=str(d_copy.get("intent_id", "")),
41
+ event_id=str(d_copy.get("event_id", "")),
42
+ causation_id=cast(str | None, d_copy.get("causation_id")),
43
+ correlation_id=str(d_copy.get("correlation_id", "")),
44
+ root_id=str(d_copy.get("root_id", "")),
45
+ timestamp_ns=int(str(d_copy.get("timestamp_ns", 0))),
46
+ metadata=cast(dict[str, object], d_copy.get("metadata", {})),
47
+ )
48
+ case "PlanGeneratedEvent":
49
+ return PlanGeneratedEvent(
50
+ workflow_id=cast(str | None, d_copy.get("workflow_id")),
51
+ intent_id=str(d_copy.get("intent_id", "")),
52
+ steps=cast(list[dict[str, object]], d_copy.get("steps", [])),
53
+ plan_id=str(d_copy.get("plan_id", "")),
54
+ event_id=str(d_copy.get("event_id", "")),
55
+ causation_id=cast(str | None, d_copy.get("causation_id")),
56
+ correlation_id=str(d_copy.get("correlation_id", "")),
57
+ root_id=str(d_copy.get("root_id", "")),
58
+ timestamp_ns=int(str(d_copy.get("timestamp_ns", 0))),
59
+ metadata=cast(dict[str, object], d_copy.get("metadata", {})),
60
+ )
61
+ case "CommandIssuedEvent":
62
+ return CommandIssuedEvent(
63
+ workflow_id=cast(str | None, d_copy.get("workflow_id")),
64
+ plan_id=str(d_copy.get("plan_id", "")),
65
+ action=str(d_copy.get("action", "")),
66
+ parameters=cast(dict[str, object], d_copy.get("parameters", {})),
67
+ command_id=str(d_copy.get("command_id", "")),
68
+ event_id=str(d_copy.get("event_id", "")),
69
+ causation_id=cast(str | None, d_copy.get("causation_id")),
70
+ correlation_id=str(d_copy.get("correlation_id", "")),
71
+ root_id=str(d_copy.get("root_id", "")),
72
+ timestamp_ns=int(str(d_copy.get("timestamp_ns", 0))),
73
+ metadata=cast(dict[str, object], d_copy.get("metadata", {})),
74
+ )
75
+ case "DriverTelemetryEvent" | "TelemetryEvent":
76
+ return DriverTelemetryEvent(
77
+ workflow_id=cast(str | None, d_copy.get("workflow_id")),
78
+ driver_id=str(d_copy.get("driver_id", "")),
79
+ status=str(d_copy.get("status", "")),
80
+ payload=cast(dict[str, object], d_copy.get("payload", {})),
81
+ event_id=str(d_copy.get("event_id", "")),
82
+ causation_id=cast(str | None, d_copy.get("causation_id")),
83
+ correlation_id=str(d_copy.get("correlation_id", "")),
84
+ root_id=str(d_copy.get("root_id", "")),
85
+ timestamp_ns=int(str(d_copy.get("timestamp_ns", 0))),
86
+ metadata=cast(dict[str, object], d_copy.get("metadata", {})),
87
+ )
88
+ case "VerificationResultEvent":
89
+ return VerificationResultEvent(
90
+ workflow_id=cast(str | None, d_copy.get("workflow_id")),
91
+ passed=bool(d_copy.get("passed", True)),
92
+ rule_id=str(d_copy.get("rule_id", "")),
93
+ details=cast(dict[str, object], d_copy.get("details", {})),
94
+ metrics=cast(dict[str, object], d_copy.get("metrics", {})),
95
+ event_id=str(d_copy.get("event_id", "")),
96
+ causation_id=cast(str | None, d_copy.get("causation_id")),
97
+ correlation_id=str(d_copy.get("correlation_id", "")),
98
+ root_id=str(d_copy.get("root_id", "")),
99
+ timestamp_ns=int(str(d_copy.get("timestamp_ns", 0))),
100
+ metadata=cast(dict[str, object], d_copy.get("metadata", {})),
101
+ )
102
+ case _:
103
+ return BaseEvent(
104
+ workflow_id=cast(str | None, d_copy.get("workflow_id")),
105
+ event_id=str(d_copy.get("event_id", "")),
106
+ causation_id=cast(str | None, d_copy.get("causation_id")),
107
+ correlation_id=str(d_copy.get("correlation_id", "")),
108
+ root_id=str(d_copy.get("root_id", "")),
109
+ timestamp_ns=int(str(d_copy.get("timestamp_ns", 0))),
110
+ metadata=cast(dict[str, object], d_copy.get("metadata", {})),
111
+ )
112
+
113
+
114
+ __all__ = [
115
+ "BaseEvent",
116
+ "CommandIssuedEvent",
117
+ "DriverTelemetryEvent",
118
+ "IntentEvent",
119
+ "PlanGeneratedEvent",
120
+ "TelemetryEvent",
121
+ "VerificationResultEvent",
122
+ "Workflow",
123
+ "WorkflowPolicy",
124
+ "WorkflowState",
125
+ "dict_to_event",
126
+ "event_to_dict",
127
+ ]
@@ -0,0 +1,3 @@
1
+ """
2
+ Cortex Developer Tools and Verification Services Package
3
+ """
@@ -0,0 +1,3 @@
1
+ """
2
+ Cortex Developer CLI Package
3
+ """