cortex-runtime 0.2.0__tar.gz → 0.2.1__tar.gz

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 (79) hide show
  1. cortex_runtime-0.2.1/NOTICE +9 -0
  2. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/PKG-INFO +5 -3
  3. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/__init__.py +2 -0
  4. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/client.py +23 -1
  5. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/compat.py +5 -3
  6. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/__init__.py +2 -0
  7. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/cli/__init__.py +2 -0
  8. cortex_runtime-0.2.1/cortex/tools/cli/main.py +233 -0
  9. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/cli/runner.py +19 -2
  10. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/__init__.py +2 -0
  11. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/actors/__init__.py +2 -0
  12. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/drivers/__init__.py +2 -0
  13. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/graph/__init__.py +2 -0
  14. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/plugin/__init__.py +2 -0
  15. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/plugin/loader.py +2 -1
  16. cortex_runtime-0.2.1/cortex/tools/kernel/plugin/manifest.py +93 -0
  17. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/schema/__init__.py +2 -0
  18. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/schema/workflow.py +5 -0
  19. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/services/__init__.py +2 -0
  20. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/services/event_store.py +6 -0
  21. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/__init__.py +2 -0
  22. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/adapters/__init__.py +2 -0
  23. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/generator/__init__.py +2 -0
  24. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/invariants/__init__.py +2 -0
  25. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/metrics/__init__.py +2 -0
  26. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/schema/__init__.py +3 -0
  27. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/pyproject.toml +4 -3
  28. cortex_runtime-0.2.0/cortex/tools/cli/main.py +0 -139
  29. cortex_runtime-0.2.0/cortex/tools/kernel/plugin/manifest.py +0 -53
  30. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/.gitignore +0 -0
  31. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/LICENSE +0 -0
  32. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/README.md +0 -0
  33. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/__main__.py +0 -0
  34. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/exceptions.py +0 -0
  35. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/plugin.py +0 -0
  36. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/py.typed +0 -0
  37. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/schema/__init__.py +0 -0
  38. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/schema/events.py +0 -0
  39. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/cli/scaffolder.py +0 -0
  40. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/gen_test_bin.py +0 -0
  41. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/actors/executor.py +0 -0
  42. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/actors/planner.py +0 -0
  43. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/context.py +0 -0
  44. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/drivers/mock_robot.py +0 -0
  45. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/drivers/rtl_verilator.py +0 -0
  46. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/graph/analyzer.py +0 -0
  47. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/graph/execution_graph.py +0 -0
  48. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/mailbox.py +0 -0
  49. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/registry.py +0 -0
  50. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/schema/contract.py +0 -0
  51. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/schema/event.py +0 -0
  52. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/schema/message.py +0 -0
  53. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/services/execution_intelligence.py +0 -0
  54. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/services/graph_builder.py +0 -0
  55. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/services/replay.py +0 -0
  56. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/services/verification.py +0 -0
  57. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/kernel/transport.py +0 -0
  58. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/run_phase2_verification.sh +0 -0
  59. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/adapters/base.py +0 -0
  60. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/adapters/coq.py +0 -0
  61. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/adapters/rtl.py +0 -0
  62. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/adapters/rust.py +0 -0
  63. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/archive.py +0 -0
  64. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/bus.py +0 -0
  65. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/contract.py +0 -0
  66. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/engine.py +0 -0
  67. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/generator/composer.py +0 -0
  68. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/generator/program.py +0 -0
  69. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/generator/state.py +0 -0
  70. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/invariants/capability.py +0 -0
  71. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/metrics/base.py +0 -0
  72. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/metrics/opcode.py +0 -0
  73. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/metrics/state_space.py +0 -0
  74. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/metrics/trap.py +0 -0
  75. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/mutation.py +0 -0
  76. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/oracle.py +0 -0
  77. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/schema/event.py +0 -0
  78. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verification/shrink.py +0 -0
  79. {cortex_runtime-0.2.0 → cortex_runtime-0.2.1}/cortex/tools/verify.py +0 -0
@@ -0,0 +1,9 @@
1
+ Cortex
2
+ Copyright 2024-2026 Iradukunda Fils
3
+
4
+ This product is licensed under the Apache License, Version 2.0 (the "License").
5
+ You may obtain a copy of the License at:
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ This product includes software developed by Iradukunda Fils.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cortex-runtime
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Spatiotemporal authority and semantic verification framework for autonomous workflows
5
5
  Project-URL: Homepage, https://github.com/Iradukunda-Fils/Cortex
6
6
  Project-URL: Documentation, https://github.com/Iradukunda-Fils/Cortex#readme
@@ -9,6 +9,7 @@ Project-URL: Issues, https://github.com/Iradukunda-Fils/Cortex/issues
9
9
  Author: Iradukunda Fils
10
10
  License: Apache-2.0
11
11
  License-File: LICENSE
12
+ License-File: NOTICE
12
13
  Keywords: agents,architecture,capability-security,sandbox,spatiotemporal,verification,workflow
13
14
  Classifier: Development Status :: 4 - Beta
14
15
  Classifier: Intended Audience :: Developers
@@ -18,6 +19,8 @@ Classifier: Programming Language :: Python :: 3
18
19
  Classifier: Programming Language :: Python :: 3.10
19
20
  Classifier: Programming Language :: Python :: 3.11
20
21
  Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
21
24
  Classifier: Topic :: Security
22
25
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
26
  Classifier: Topic :: System :: Distributed Computing
@@ -27,10 +30,9 @@ Requires-Dist: pyyaml<7.0.0,>=6.0.0
27
30
  Requires-Dist: typing-extensions>=4.5.0
28
31
  Provides-Extra: dev
29
32
  Requires-Dist: build>=1.0.0; extra == 'dev'
33
+ Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
30
34
  Requires-Dist: pyright>=1.1.0; extra == 'dev'
31
- Requires-Dist: pytest>=7.0.0; extra == 'dev'
32
35
  Requires-Dist: ruff>=0.1.0; extra == 'dev'
33
- Requires-Dist: twine>=4.0.0; extra == 'dev'
34
36
  Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
35
37
  Provides-Extra: docs
36
38
  Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
@@ -6,6 +6,7 @@ workflow boundary management, sandboxed capability negotiation, and verification
6
6
  """
7
7
 
8
8
  from cortex.client import CortexClient
9
+ from cortex.compat import override
9
10
  from cortex.exceptions import (
10
11
  CapabilityViolationError,
11
12
  CortexError,
@@ -48,4 +49,5 @@ __all__ = [
48
49
  "WorkflowExecutionError",
49
50
  "WorkflowPolicy",
50
51
  "WorkflowState",
52
+ "override",
51
53
  ]
@@ -76,6 +76,12 @@ class CortexClient:
76
76
 
77
77
  def register_plugin(self, plugin: BasePlugin) -> PluginRegistration:
78
78
  """Register a plugin with capability negotiation."""
79
+ # Prevent duplicate transport subscriptions if exact plugin instance is re-registered
80
+ if plugin in self.registered_plugins:
81
+ existing = self.registry.get_plugin(plugin.manifest.name)
82
+ if existing:
83
+ return existing
84
+
79
85
  registration = self.registry.register(plugin.manifest)
80
86
  if registration.state == PluginState.ACTIVE:
81
87
  context = PluginContext(
@@ -99,7 +105,23 @@ class CortexClient:
99
105
  def _dispatch_to_plugin(self, plugin: BasePlugin, event: AnyEvent) -> None:
100
106
  """Helper to safely dispatch event to plugin if active and consuming."""
101
107
  if plugin.context and isinstance(event, BaseEvent) and type(event).__name__ in plugin.manifest.consumes_events:
102
- plugin.on_event(event)
108
+ try:
109
+ plugin.on_event(event)
110
+ except Exception as err:
111
+ failure_event = VerificationResultEvent(
112
+ workflow_id=event.workflow_id,
113
+ causation_id=event.event_id,
114
+ passed=False,
115
+ rule_id="PLUGIN_EXECUTION_ERROR",
116
+ details={
117
+ "plugin": plugin.manifest.name,
118
+ "error_type": type(err).__name__,
119
+ "error_message": str(err),
120
+ "consumed_event_id": event.event_id,
121
+ "consumed_event_type": type(event).__name__,
122
+ },
123
+ )
124
+ self.transport.publish(failure_event)
103
125
 
104
126
  def create_workflow(self, name: str, goal: str, policy: WorkflowPolicy | None = None) -> Workflow:
105
127
  """Instantiate a new Workflow primitive."""
@@ -2,14 +2,15 @@
2
2
  Zero-dependency compatibility helpers for Python 3.10+
3
3
  """
4
4
 
5
+ import sys
5
6
  from collections.abc import Callable
6
7
  from typing import TypeVar
7
8
 
8
9
  F = TypeVar("F", bound=Callable[..., object])
9
10
 
10
- try:
11
- from typing import override as override # type: ignore[attr-defined]
12
- except ImportError:
11
+ if sys.version_info >= (3, 12):
12
+ from typing import override as override
13
+ else:
13
14
  try:
14
15
  from typing_extensions import override as override # type: ignore[no-redef]
15
16
  except ImportError:
@@ -18,3 +19,4 @@ except ImportError:
18
19
 
19
20
 
20
21
  __all__ = ["override"]
22
+
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Cortex Developer Tools and Verification Services Package
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Cortex Developer CLI Package
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -0,0 +1,233 @@
1
+ """
2
+ Cortex Developer CLI Command Entrypoint
3
+
4
+ Usage:
5
+ cortex init <project_name> [--type {app|plugin}] [--json]
6
+ cortex workflow run <workflow_file> [--output <file>] [--json]
7
+ cortex workflow inspect <workflow_id_or_file> [--json]
8
+ cortex workflow replay <workflow_id_or_file> [--json]
9
+ """
10
+
11
+ import argparse
12
+ import json
13
+ import os
14
+ import sys
15
+ from collections.abc import Sequence
16
+ from typing import cast
17
+
18
+ from cortex.exceptions import (
19
+ CapabilityViolationError,
20
+ CortexError,
21
+ ManifestError,
22
+ WorkflowExecutionError,
23
+ )
24
+ from cortex.tools.cli.runner import inspect_workflow, replay_workflow, run_workflow_file
25
+ from cortex.tools.cli.scaffolder import scaffold_project
26
+
27
+
28
+ def _handle_cli_error(err: Exception, json_mode: bool = False) -> int:
29
+ """Standardized CLI error renderer and exit code mapper.
30
+
31
+ Outputs formatted diagnostic blocks or machine JSON strictly to sys.stderr.
32
+ """
33
+ if isinstance(err, CapabilityViolationError):
34
+ error_code = "CAPABILITY_VIOLATION"
35
+ exit_code = err.exit_code # 2
36
+ message = err.message
37
+ cause = f"Action requested capability '{err.capability}' which was denied or not declared."
38
+ remediation = f"Add capability '{err.capability}' to required_capabilities in your plugin manifest."
39
+ details: dict[str, object] | None = {"capability": err.capability} if err.capability else None
40
+ elif isinstance(err, ManifestError):
41
+ error_code = "INVALID_MANIFEST"
42
+ exit_code = err.exit_code # 3
43
+ message = err.message
44
+ cause = "Plugin manifest failed structural validation checks."
45
+ remediation = "Ensure plugin manifest contains non-empty 'name', 'version', and valid collections."
46
+ details = None
47
+ elif isinstance(err, WorkflowExecutionError):
48
+ error_code = "WORKFLOW_FAILED"
49
+ exit_code = err.exit_code # 1
50
+ message = err.message
51
+ cause = "Workflow execution was aborted or failed verification checks."
52
+ remediation = "Inspect trace log using 'cortex workflow inspect <trace>' for failed verification nodes."
53
+ details = {"workflow_id": err.workflow_id} if err.workflow_id else None
54
+ elif isinstance(err, CortexError):
55
+ error_code = "CORTEX_ERROR"
56
+ exit_code = err.exit_code # 1
57
+ message = err.message
58
+ cause = "Cortex framework error occurred."
59
+ remediation = "Verify workflow specification and input parameters."
60
+ details = None
61
+ else:
62
+ error_code = "GENERAL_ERROR"
63
+ exit_code = getattr(os, "EX_SOFTWARE", 1)
64
+ message = str(err) or "An unexpected runtime error occurred."
65
+ cause = f"Uncaught exception of type '{type(err).__name__}'."
66
+ remediation = "Check environment setup, dependencies, and command line arguments."
67
+ details = {"error_type": type(err).__name__}
68
+
69
+ if json_mode:
70
+ payload: dict[str, object] = {
71
+ "status": "error",
72
+ "error_code": error_code,
73
+ "exit_code": exit_code,
74
+ "message": message,
75
+ "cause": cause,
76
+ "remediation": remediation,
77
+ }
78
+ if details is not None:
79
+ payload["details"] = details
80
+ print(json.dumps(payload, indent=2), file=sys.stderr)
81
+ else:
82
+ print("=================================================================", file=sys.stderr)
83
+ print(" CORTEX CLI DIAGNOSTIC ERROR REPORT ", file=sys.stderr)
84
+ print("=================================================================", file=sys.stderr)
85
+ print(f"[!] ERROR CODE: {error_code} (Exit Code {exit_code})", file=sys.stderr)
86
+ print(f"[!] MESSAGE: {message}", file=sys.stderr)
87
+ print(f"[!] CAUSE: {cause}", file=sys.stderr)
88
+ print(f"[!] REMEDIATION: {remediation}", file=sys.stderr)
89
+ print("=================================================================", file=sys.stderr)
90
+
91
+ return exit_code
92
+
93
+
94
+ def cli_entrypoint() -> None:
95
+ """Console script entrypoint for PyPI cortex-runtime executable."""
96
+ sys.exit(main())
97
+
98
+
99
+ def main(argv: Sequence[str] | None = None) -> int:
100
+ """Main CLI entrypoint for Cortex framework."""
101
+ if argv is None:
102
+ argv = sys.argv[1:]
103
+
104
+ parser = argparse.ArgumentParser(
105
+ prog="cortex",
106
+ description="Cortex Platform Developer CLI & Workflow Engine",
107
+ )
108
+ parser.add_argument(
109
+ "--json",
110
+ action="store_true",
111
+ help="Output machine-readable JSON format",
112
+ )
113
+
114
+ subparsers = parser.add_subparsers(dest="command", help="Command to execute")
115
+
116
+ # cortex init
117
+ init_parser = subparsers.add_parser("init", help="Scaffold a new Cortex plugin or application")
118
+ _ = init_parser.add_argument("project_name", help="Name of the project directory to create")
119
+ _ = init_parser.add_argument(
120
+ "--type",
121
+ choices=["app", "plugin"],
122
+ default="app",
123
+ help="Type of project to scaffold (default: app)",
124
+ )
125
+
126
+ # cortex workflow
127
+ wf_parser = subparsers.add_parser("workflow", help="Workflow execution and inspection management")
128
+ wf_sub = wf_parser.add_subparsers(dest="wf_command", help="Workflow subcommand")
129
+
130
+ # cortex workflow run
131
+ wf_run = wf_sub.add_parser("run", help="Trigger workflow execution from spec file")
132
+ _ = wf_run.add_argument("workflow_file", help="Path to workflow definition JSON file")
133
+ _ = wf_run.add_argument("--output", "-o", help="Optional path to save event journal JSON trace")
134
+
135
+ # cortex workflow inspect
136
+ wf_inspect = wf_sub.add_parser("inspect", help="Inspect execution graph and lineage for workflow ID or file")
137
+ _ = wf_inspect.add_argument("workflow_id", help="Workflow ID or path to event trace JSON file")
138
+
139
+ # cortex workflow replay
140
+ wf_replay = wf_sub.add_parser("replay", help="Deterministically replay workflow execution trace")
141
+ _ = wf_replay.add_argument("workflow_id", help="Workflow ID or path to event trace JSON file")
142
+
143
+ args = parser.parse_args(argv)
144
+ cmd = str(getattr(args, "command", ""))
145
+ wf_cmd = str(getattr(args, "wf_command", ""))
146
+ json_mode = bool(getattr(args, "json", False))
147
+
148
+ try:
149
+ if cmd == "init":
150
+ p_name = str(getattr(args, "project_name", "my_cortex_app"))
151
+ p_type = str(getattr(args, "type", "app"))
152
+ path = scaffold_project(p_name, project_type=p_type)
153
+ if json_mode:
154
+ print(json.dumps({"status": "success", "command": "init", "project": p_name, "path": path}))
155
+ else:
156
+ print(f"[+] Successfully scaffolded Cortex {p_type} project at: {path}")
157
+ return 0
158
+
159
+ elif cmd == "workflow":
160
+ if wf_cmd == "run":
161
+ wf_file = str(getattr(args, "workflow_file", ""))
162
+ out_file = cast(str | None, getattr(args, "output", None))
163
+ res = run_workflow_file(wf_file, output_file=out_file)
164
+ if json_mode:
165
+ print(json.dumps({"status": "success", "command": "workflow run", "result": res}))
166
+ else:
167
+ print("[+] Workflow execution finished.")
168
+ print(f" ID: {res['workflow_id']}")
169
+ print(f" State: {res['state']}")
170
+ print(f" Events Log: {res['event_count']}")
171
+ print(f" Trace Saved: {res['output_file']}")
172
+ return 0
173
+
174
+ elif wf_cmd == "inspect":
175
+ wf_id = str(getattr(args, "workflow_id", ""))
176
+ res = inspect_workflow(wf_id)
177
+ if json_mode:
178
+ print(json.dumps({"status": "success", "command": "workflow inspect", "result": res}))
179
+ else:
180
+ causality_tree = cast(list[str], res.get("causality_tree", []))
181
+ failed_nodes = cast(list[dict[str, object]], res.get("failed_nodes", []))
182
+
183
+ print("=== Cortex Execution Graph Inspection ===")
184
+ print(f"Workflow ID: {res['workflow_id']}")
185
+ print(f"Name: {res['name']}")
186
+ print(f"Goal: {res['goal']}")
187
+ print(f"State: {res['state']}")
188
+ print(f"Total Nodes: {res['node_count']}")
189
+ print("\n--- Causality Tree ---")
190
+ for line in causality_tree:
191
+ print(f" {line}")
192
+ if failed_nodes:
193
+ print(f"\n[!] Verification Failures ({len(failed_nodes)}):")
194
+ for node in failed_nodes:
195
+ print(f" - Node {node['id']}: {node['payload']}")
196
+ else:
197
+ print("\n[+] Verification Status: ALL PASSED")
198
+ return 0
199
+
200
+ elif wf_cmd == "replay":
201
+ wf_id = str(getattr(args, "workflow_id", ""))
202
+ res = replay_workflow(wf_id)
203
+ is_deterministic = bool(res.get("deterministic", False))
204
+ if json_mode:
205
+ print(json.dumps({"status": "success" if is_deterministic else "error", "command": "workflow replay", "result": res}))
206
+ else:
207
+ print("=== Cortex Deterministic Replay Engine ===")
208
+ print(f"Workflow ID: {res['workflow_id']}")
209
+ print(f"Events Replayed: {res['events_replayed']}")
210
+ print(f"Status: {'SUCCESS' if is_deterministic else 'FAILED'}")
211
+ print(f"Result: {res['verification_result']}")
212
+
213
+ if not is_deterministic:
214
+ if not json_mode:
215
+ _ = _handle_cli_error(WorkflowExecutionError(f"Replay divergence detected for workflow trace: {wf_id}"), json_mode=False)
216
+ return 1
217
+ return 0
218
+
219
+ else:
220
+ wf_parser.print_help(sys.stderr if not json_mode else sys.stdout)
221
+ return _handle_cli_error(WorkflowExecutionError("Missing or invalid workflow subcommand"), json_mode=json_mode)
222
+
223
+ else:
224
+ parser.print_help(sys.stderr if not json_mode else sys.stdout)
225
+ return _handle_cli_error(WorkflowExecutionError("Missing or invalid command"), json_mode=json_mode)
226
+
227
+ except Exception as err:
228
+ return _handle_cli_error(err, json_mode=json_mode)
229
+
230
+
231
+
232
+ if __name__ == "__main__":
233
+ sys.exit(main())
@@ -10,8 +10,8 @@ import os
10
10
  from typing import cast
11
11
 
12
12
  from cortex.client import CortexClient
13
- from cortex.exceptions import WorkflowExecutionError
14
- from cortex.schema import IntentEvent, WorkflowPolicy
13
+ from cortex.exceptions import CapabilityViolationError, WorkflowExecutionError
14
+ from cortex.schema import IntentEvent, VerificationResultEvent, WorkflowPolicy, WorkflowState
15
15
 
16
16
 
17
17
  def run_workflow_file(workflow_file: str, output_file: str | None = None) -> dict[str, str | int]:
@@ -55,6 +55,23 @@ def run_workflow_file(workflow_file: str, output_file: str | None = None) -> dic
55
55
 
56
56
  saved_path = client.save_trace(executed_wf.workflow_id, output_file, name=wf_name, goal=wf_goal)
57
57
 
58
+ if executed_wf.state == WorkflowState.FAILED:
59
+ cap_failures = [
60
+ e for e in client.event_store.get_log()
61
+ if isinstance(e, VerificationResultEvent) and not e.passed and (e.rule_id == "CAPABILITY_VIOLATION" or "capability" in e.details)
62
+ ]
63
+ if cap_failures:
64
+ detail = cap_failures[0].details
65
+ cap_name = str(detail.get("capability", detail.get("required_capability", "unknown")))
66
+ raise CapabilityViolationError(
67
+ f"Workflow execution failed due to capability violation: '{cap_name}'",
68
+ capability=cap_name,
69
+ )
70
+ raise WorkflowExecutionError(
71
+ f"Workflow '{wf_name}' ({executed_wf.workflow_id}) failed verification checks.",
72
+ workflow_id=executed_wf.workflow_id,
73
+ )
74
+
58
75
  return {
59
76
  "workflow_id": executed_wf.workflow_id,
60
77
  "state": executed_wf.state.value,
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Cortex Kernel Runtime Core
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Kernel Actors Infrastructure
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Kernel Drivers & Adapters
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Kernel Causal Execution Graph Engine
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Kernel Plugin Runtime & Capability Negotiation
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -9,7 +9,7 @@ to their declared capabilities — never raw kernel internals.
9
9
  import enum
10
10
  from dataclasses import dataclass, field
11
11
 
12
- from cortex.tools.kernel.plugin.manifest import PluginManifest
12
+ from cortex.tools.kernel.plugin.manifest import PluginManifest, validate_manifest
13
13
 
14
14
 
15
15
  class PluginState(str, enum.Enum):
@@ -40,6 +40,7 @@ class CapabilityNegotiator:
40
40
  def negotiate(self, manifest: PluginManifest) -> PluginRegistration:
41
41
  """Evaluates a plugin manifest and returns a PluginRegistration
42
42
  with granted/denied capability sets."""
43
+ validate_manifest(manifest)
43
44
  registration = PluginRegistration(manifest=manifest, state=PluginState.NEGOTIATING)
44
45
 
45
46
  granted: set[str] = set()
@@ -0,0 +1,93 @@
1
+ """
2
+ Declarative Plugin Manifest Schema
3
+
4
+ Every plugin declares its event consumption/production contract and the
5
+ kernel capabilities it requires. The Kernel enforces capability negotiation
6
+ at registration time — no raw access to internals is ever granted.
7
+ """
8
+
9
+ from dataclasses import dataclass, field
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class PluginManifest:
14
+ """Immutable declaration of a plugin's identity, event contract,
15
+ and required kernel capabilities."""
16
+ name: str
17
+ version: str
18
+ description: str
19
+ consumes_events: list[str] = field(default_factory=list)
20
+ produces_events: list[str] = field(default_factory=list)
21
+ required_capabilities: list[str] = field(default_factory=list)
22
+
23
+
24
+ def validate_manifest(manifest: PluginManifest) -> None:
25
+ """Validates the structural integrity of a PluginManifest.
26
+
27
+ Raises:
28
+ ManifestError: If any manifest field violates structural constraints.
29
+ """
30
+ from cortex.exceptions import ManifestError
31
+
32
+ if not isinstance(manifest, PluginManifest):
33
+ raise ManifestError(f"Expected PluginManifest instance, got {type(manifest).__name__}")
34
+
35
+ if not isinstance(manifest.name, str) or not manifest.name.strip():
36
+ raise ManifestError("Plugin manifest 'name' must be a non-empty string")
37
+
38
+ if not isinstance(manifest.version, str) or not manifest.version.strip():
39
+ raise ManifestError("Plugin manifest 'version' must be a non-empty string")
40
+
41
+ if not isinstance(manifest.description, str):
42
+ raise ManifestError("Plugin manifest 'description' must be a string")
43
+
44
+ if not isinstance(manifest.consumes_events, (list, tuple)):
45
+ raise ManifestError("Plugin manifest 'consumes_events' must be a sequence of strings")
46
+ for item in manifest.consumes_events:
47
+ if not isinstance(item, str) or not item.strip():
48
+ raise ManifestError("Plugin manifest 'consumes_events' elements must be non-empty strings")
49
+
50
+ if not isinstance(manifest.produces_events, (list, tuple)):
51
+ raise ManifestError("Plugin manifest 'produces_events' must be a sequence of strings")
52
+ for item in manifest.produces_events:
53
+ if not isinstance(item, str) or not item.strip():
54
+ raise ManifestError("Plugin manifest 'produces_events' elements must be non-empty strings")
55
+
56
+ if not isinstance(manifest.required_capabilities, (list, tuple)):
57
+ raise ManifestError("Plugin manifest 'required_capabilities' must be a sequence of strings")
58
+ for item in manifest.required_capabilities:
59
+ if not isinstance(item, str) or not item.strip():
60
+ raise ManifestError("Plugin manifest 'required_capabilities' elements must be non-empty strings")
61
+
62
+
63
+
64
+ # -----------------------------------------------------------------------
65
+ # Reference Manifests — canonical examples of domain plugin declarations
66
+ # -----------------------------------------------------------------------
67
+
68
+ ROBOT_ARM_MANIFEST = PluginManifest(
69
+ name="robot-arm-driver",
70
+ version="0.1.0",
71
+ description="Interface for 6-DOF industrial robot arm",
72
+ consumes_events=["CommandIssuedEvent"],
73
+ produces_events=["DriverTelemetryEvent"],
74
+ required_capabilities=["hardware.actuators.execute", "hardware.telemetry.read"],
75
+ )
76
+
77
+ AGENT_PLANNER_MANIFEST = PluginManifest(
78
+ name="llm-task-planner",
79
+ version="0.1.0",
80
+ description="Decomposes goal intents into step-wise plans",
81
+ consumes_events=["IntentEvent"],
82
+ produces_events=["PlanGeneratedEvent"],
83
+ required_capabilities=["workflow.plan.create"],
84
+ )
85
+
86
+ VERIFICATION_SERVICE_MANIFEST = PluginManifest(
87
+ name="verification-service",
88
+ version="0.1.0",
89
+ description="Formal verification oracle for CommitContractV1",
90
+ consumes_events=["DriverTelemetryEvent", "CommitEventV1"],
91
+ produces_events=["VerificationResultEvent"],
92
+ required_capabilities=["verification.oracle.execute", "verification.invariant.check"],
93
+ )
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Kernel Schema & Domain Event Hierarchy
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -9,6 +9,11 @@ from dataclasses import dataclass, field
9
9
 
10
10
 
11
11
  class WorkflowState(str, enum.Enum):
12
+ """Lifecycle state of a Cortex workflow execution.
13
+
14
+ Transitions: PENDING → RUNNING → COMPLETED | FAILED | ABORTED
15
+ """
16
+
12
17
  PENDING = "PENDING"
13
18
  RUNNING = "RUNNING"
14
19
  COMPLETED = "COMPLETED"
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Kernel Services Layer
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -7,6 +7,12 @@ from cortex.tools.kernel.transport import AnyEvent
7
7
 
8
8
 
9
9
  class EventStoreService:
10
+ """Append-only event journal that records all domain events for a workflow.
11
+
12
+ Provides ordered event retrieval for trace persistence, inspection,
13
+ and deterministic replay. This is the public EventStore interface
14
+ re-exported as ``cortex.EventStore``.
15
+ """
10
16
  _log: list[AnyEvent]
11
17
 
12
18
  contract: ServiceContract = ServiceContract(
@@ -3,3 +3,5 @@ Cortex Verification Platform Core Package
3
3
  """
4
4
 
5
5
  __version__ = "1.0.0"
6
+
7
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Trace Adapters for Coq, Rust, and SystemVerilog Execution Engines
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Scenario & Machine State Generators
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Unary Capability Safety Invariant Plugins
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -1,3 +1,5 @@
1
1
  """
2
2
  Multi-Dimensional Metric Plugins
3
3
  """
4
+
5
+ __all__: list[str] = []
@@ -2,6 +2,9 @@
2
2
  Typed Verification Schemas Package
3
3
  """
4
4
 
5
+ __all__: list[str] = []
6
+
7
+
5
8
  from dataclasses import asdict, dataclass
6
9
 
7
10
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cortex-runtime"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Spatiotemporal authority and semantic verification framework for autonomous workflows"
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -30,6 +30,8 @@ classifiers = [
30
30
  "Programming Language :: Python :: 3.10",
31
31
  "Programming Language :: Python :: 3.11",
32
32
  "Programming Language :: Python :: 3.12",
33
+ "Programming Language :: Python :: 3.13",
34
+ "Programming Language :: Python :: 3.14",
33
35
  "Topic :: Security",
34
36
  "Topic :: Software Development :: Libraries :: Python Modules",
35
37
  "Topic :: System :: Distributed Computing",
@@ -44,9 +46,8 @@ dependencies = [
44
46
  dev = [
45
47
  "ruff>=0.1.0",
46
48
  "pyright>=1.1.0",
47
- "pytest>=7.0.0",
48
49
  "build>=1.0.0",
49
- "twine>=4.0.0",
50
+ "pre-commit>=3.0.0",
50
51
  "types-pyyaml>=6.0.0",
51
52
  ]
52
53
  docs = [
@@ -1,139 +0,0 @@
1
- """
2
- Cortex Developer CLI Command Entrypoint
3
-
4
- Usage:
5
- cortex init <project_name> [--type {app|plugin}]
6
- cortex workflow run <workflow_file> [--output <file>]
7
- cortex workflow inspect <workflow_id_or_file>
8
- cortex workflow replay <workflow_id_or_file>
9
- """
10
-
11
- import argparse
12
- import os
13
- import sys
14
- from collections.abc import Sequence
15
- from typing import cast
16
-
17
- from cortex.exceptions import CortexError
18
- from cortex.tools.cli.runner import inspect_workflow, replay_workflow, run_workflow_file
19
- from cortex.tools.cli.scaffolder import scaffold_project
20
-
21
-
22
- def cli_entrypoint() -> None:
23
- """Console script entrypoint for PyPI cortex-runtime executable."""
24
- sys.exit(main())
25
-
26
-
27
- def main(argv: Sequence[str] | None = None) -> int:
28
- """Main CLI entrypoint for Cortex framework."""
29
- if argv is None:
30
- argv = sys.argv[1:]
31
-
32
- parser = argparse.ArgumentParser(
33
- prog="cortex",
34
- description="Cortex Platform Developer CLI & Workflow Engine",
35
- )
36
- subparsers = parser.add_subparsers(dest="command", help="Command to execute")
37
-
38
- # cortex init
39
- init_parser = subparsers.add_parser("init", help="Scaffold a new Cortex plugin or application")
40
- _ = init_parser.add_argument("project_name", help="Name of the project directory to create")
41
- _ = init_parser.add_argument(
42
- "--type",
43
- choices=["app", "plugin"],
44
- default="app",
45
- help="Type of project to scaffold (default: app)",
46
- )
47
-
48
- # cortex workflow
49
- wf_parser = subparsers.add_parser("workflow", help="Workflow execution and inspection management")
50
- wf_sub = wf_parser.add_subparsers(dest="wf_command", help="Workflow subcommand")
51
-
52
- # cortex workflow run
53
- wf_run = wf_sub.add_parser("run", help="Trigger workflow execution from spec file")
54
- _ = wf_run.add_argument("workflow_file", help="Path to workflow definition JSON file")
55
- _ = wf_run.add_argument("--output", "-o", help="Optional path to save event journal JSON trace")
56
-
57
- # cortex workflow inspect
58
- wf_inspect = wf_sub.add_parser("inspect", help="Inspect execution graph and lineage for workflow ID or file")
59
- _ = wf_inspect.add_argument("workflow_id", help="Workflow ID or path to event trace JSON file")
60
-
61
- # cortex workflow replay
62
- wf_replay = wf_sub.add_parser("replay", help="Deterministically replay workflow execution trace")
63
- _ = wf_replay.add_argument("workflow_id", help="Workflow ID or path to event trace JSON file")
64
-
65
- args = parser.parse_args(argv)
66
- cmd = str(getattr(args, "command", ""))
67
- wf_cmd = str(getattr(args, "wf_command", ""))
68
-
69
- try:
70
- if cmd == "init":
71
- p_name = str(getattr(args, "project_name", "my_cortex_app"))
72
- p_type = str(getattr(args, "type", "app"))
73
- path = scaffold_project(p_name, project_type=p_type)
74
- print(f"[+] Successfully scaffolded Cortex {p_type} project at: {path}")
75
- return 0
76
-
77
- elif cmd == "workflow":
78
- if wf_cmd == "run":
79
- wf_file = str(getattr(args, "workflow_file", ""))
80
- out_file = cast(str | None, getattr(args, "output", None))
81
- res = run_workflow_file(wf_file, output_file=out_file)
82
- print("[+] Workflow execution finished.")
83
- print(f" ID: {res['workflow_id']}")
84
- print(f" State: {res['state']}")
85
- print(f" Events Log: {res['event_count']}")
86
- print(f" Trace Saved: {res['output_file']}")
87
- return 0
88
-
89
- elif wf_cmd == "inspect":
90
- wf_id = str(getattr(args, "workflow_id", ""))
91
- res = inspect_workflow(wf_id)
92
- causality_tree = cast(list[str], res.get("causality_tree", []))
93
- failed_nodes = cast(list[dict[str, object]], res.get("failed_nodes", []))
94
-
95
- print("=== Cortex Execution Graph Inspection ===")
96
- print(f"Workflow ID: {res['workflow_id']}")
97
- print(f"Name: {res['name']}")
98
- print(f"Goal: {res['goal']}")
99
- print(f"State: {res['state']}")
100
- print(f"Total Nodes: {res['node_count']}")
101
- print("\n--- Causality Tree ---")
102
- for line in causality_tree:
103
- print(f" {line}")
104
- if failed_nodes:
105
- print(f"\n[!] Verification Failures ({len(failed_nodes)}):")
106
- for node in failed_nodes:
107
- print(f" - Node {node['id']}: {node['payload']}")
108
- else:
109
- print("\n[+] Verification Status: ALL PASSED")
110
- return 0
111
-
112
- elif wf_cmd == "replay":
113
- wf_id = str(getattr(args, "workflow_id", ""))
114
- res = replay_workflow(wf_id)
115
- print("=== Cortex Deterministic Replay Engine ===")
116
- print(f"Workflow ID: {res['workflow_id']}")
117
- print(f"Events Replayed: {res['events_replayed']}")
118
- print(f"Status: {'SUCCESS' if res['deterministic'] else 'FAILED'}")
119
- print(f"Result: {res['verification_result']}")
120
- return 0 if res["deterministic"] else 1
121
-
122
- else:
123
- wf_parser.print_help(sys.stderr)
124
- return 1
125
-
126
- else:
127
- parser.print_help(sys.stderr)
128
- return 1
129
-
130
- except CortexError as err:
131
- print(f"[!] Cortex Error: {err.message}", file=sys.stderr)
132
- return err.exit_code
133
- except Exception as err:
134
- print(f"[!] Unexpected Error: {err}", file=sys.stderr)
135
- return getattr(os, "EX_SOFTWARE", 1)
136
-
137
-
138
- if __name__ == "__main__":
139
- sys.exit(main())
@@ -1,53 +0,0 @@
1
- """
2
- Declarative Plugin Manifest Schema
3
-
4
- Every plugin declares its event consumption/production contract and the
5
- kernel capabilities it requires. The Kernel enforces capability negotiation
6
- at registration time — no raw access to internals is ever granted.
7
- """
8
-
9
- from dataclasses import dataclass, field
10
-
11
-
12
- @dataclass(frozen=True)
13
- class PluginManifest:
14
- """Immutable declaration of a plugin's identity, event contract,
15
- and required kernel capabilities."""
16
- name: str
17
- version: str
18
- description: str
19
- consumes_events: list[str] = field(default_factory=list)
20
- produces_events: list[str] = field(default_factory=list)
21
- required_capabilities: list[str] = field(default_factory=list)
22
-
23
-
24
- # -----------------------------------------------------------------------
25
- # Reference Manifests — canonical examples of domain plugin declarations
26
- # -----------------------------------------------------------------------
27
-
28
- ROBOT_ARM_MANIFEST = PluginManifest(
29
- name="robot-arm-driver",
30
- version="0.1.0",
31
- description="Interface for 6-DOF industrial robot arm",
32
- consumes_events=["CommandIssuedEvent"],
33
- produces_events=["DriverTelemetryEvent"],
34
- required_capabilities=["hardware.actuators.execute", "hardware.telemetry.read"],
35
- )
36
-
37
- AGENT_PLANNER_MANIFEST = PluginManifest(
38
- name="llm-task-planner",
39
- version="0.1.0",
40
- description="Decomposes goal intents into step-wise plans",
41
- consumes_events=["IntentEvent"],
42
- produces_events=["PlanGeneratedEvent"],
43
- required_capabilities=["workflow.plan.create"],
44
- )
45
-
46
- VERIFICATION_SERVICE_MANIFEST = PluginManifest(
47
- name="verification-service",
48
- version="0.1.0",
49
- description="Formal verification oracle for CommitContractV1",
50
- consumes_events=["DriverTelemetryEvent", "CommitEventV1"],
51
- produces_events=["VerificationResultEvent"],
52
- required_capabilities=["verification.oracle.execute", "verification.invariant.check"],
53
- )
File without changes
File without changes