clm-kernel 0.0.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 (333) hide show
  1. clm/__init__.py +230 -0
  2. clm/__main__.py +25 -0
  3. clm/cross_cutting/__init__.py +50 -0
  4. clm/cross_cutting/_test_runner.py +36 -0
  5. clm/cross_cutting/async_utils.py +25 -0
  6. clm/cross_cutting/cel_builder.py +123 -0
  7. clm/cross_cutting/cel_converter.py +697 -0
  8. clm/cross_cutting/cel_engine.py +252 -0
  9. clm/cross_cutting/cel_ops.py +72 -0
  10. clm/cross_cutting/cel_ops_db.py +157 -0
  11. clm/cross_cutting/cel_ops_files.py +99 -0
  12. clm/cross_cutting/cel_ops_state.py +71 -0
  13. clm/cross_cutting/cel_ops_strings.py +64 -0
  14. clm/cross_cutting/cel_resolver.py +63 -0
  15. clm/cross_cutting/cel_slices.py +56 -0
  16. clm/cross_cutting/cel_store.py +330 -0
  17. clm/cross_cutting/clm_logger.py +140 -0
  18. clm/cross_cutting/config/__init__.py +155 -0
  19. clm/cross_cutting/config/config_constants.py +392 -0
  20. clm/cross_cutting/config/env_parameters.py +90 -0
  21. clm/cross_cutting/config/logging.py +378 -0
  22. clm/cross_cutting/config/settings.py +504 -0
  23. clm/cross_cutting/context.py +5 -0
  24. clm/cross_cutting/domain_models.py +55 -0
  25. clm/cross_cutting/domain_types.py +61 -0
  26. clm/cross_cutting/effects.py +67 -0
  27. clm/cross_cutting/errors.py +153 -0
  28. clm/cross_cutting/governance.py +331 -0
  29. clm/cross_cutting/guards.py +41 -0
  30. clm/cross_cutting/mcard.py +321 -0
  31. clm/cross_cutting/native.py +185 -0
  32. clm/cross_cutting/observability.py +289 -0
  33. clm/cross_cutting/pcard.py +434 -0
  34. clm/cross_cutting/registry.py +71 -0
  35. clm/cross_cutting/resources.py +84 -0
  36. clm/cross_cutting/secrets.py +44 -0
  37. clm/cross_cutting/subprocess_utils.py +118 -0
  38. clm/cross_cutting/telemetry.py +164 -0
  39. clm/cross_cutting/testing/__init__.py +8 -0
  40. clm/cross_cutting/testing/comparator.py +187 -0
  41. clm/cross_cutting/testing/datasets.py +87 -0
  42. clm/cross_cutting/timeutil.py +20 -0
  43. clm/cross_cutting/types/new_type_check.py +0 -0
  44. clm/cross_cutting/utils/__init__.py +1 -0
  45. clm/cross_cutting/utils/url_safety.py +50 -0
  46. clm/cross_cutting/vcard.py +560 -0
  47. clm/cross_cutting/writer.py +118 -0
  48. clm/layer0/README.md +50 -0
  49. clm/layer0/__init__.py +223 -0
  50. clm/layer0/algebra.py +60 -0
  51. clm/layer0/algebra_baldwin.py +133 -0
  52. clm/layer0/algebra_baldwin_generators.py +36 -0
  53. clm/layer0/algebra_equivalence.py +262 -0
  54. clm/layer0/algebra_ingest.py +306 -0
  55. clm/layer0/algebra_manifest_io.py +156 -0
  56. clm/layer0/assembler.py +481 -0
  57. clm/layer0/cel/__init__.py +23 -0
  58. clm/layer0/cel_eval.py +491 -0
  59. clm/layer0/codec.py +106 -0
  60. clm/layer0/context.py +122 -0
  61. clm/layer0/db.py +160 -0
  62. clm/layer0/exceptions.py +73 -0
  63. clm/layer0/fibration.py +106 -0
  64. clm/layer0/gates.py +50 -0
  65. clm/layer0/hash.py +80 -0
  66. clm/layer0/loader.py +826 -0
  67. clm/layer0/math_utils.py +163 -0
  68. clm/layer0/mcard.py +96 -0
  69. clm/layer0/model/__init__.py +0 -0
  70. clm/layer0/model/action.py +223 -0
  71. clm/layer0/model/card.py +280 -0
  72. clm/layer0/model/card_triad.py +427 -0
  73. clm/layer0/model/compatibility.py +60 -0
  74. clm/layer0/model/dictionary.py +46 -0
  75. clm/layer0/model/dots.py +331 -0
  76. clm/layer0/model/event_producer.py +88 -0
  77. clm/layer0/model/g_time.py +89 -0
  78. clm/layer0/model/handle.py +163 -0
  79. clm/layer0/model/hash/__init__.py +6 -0
  80. clm/layer0/model/hash/algorithms/__init__.py +3 -0
  81. clm/layer0/model/hash/algorithms/custom_hash.py +7 -0
  82. clm/layer0/model/hash/algorithms/local_sha256.py +178 -0
  83. clm/layer0/model/hash/constants.py +53 -0
  84. clm/layer0/model/hash/enums.py +60 -0
  85. clm/layer0/model/hash/validator.py +307 -0
  86. clm/layer0/model/interpreter.py +275 -0
  87. clm/layer0/model/pagination.py +45 -0
  88. clm/layer0/model/pcard.py +716 -0
  89. clm/layer0/model/schema.py +44 -0
  90. clm/layer0/model/utils/__init__.py +1 -0
  91. clm/layer0/model/utils/content_analyzer.py +152 -0
  92. clm/layer0/model/validators/__init__.py +1 -0
  93. clm/layer0/model/validators/base_validator.py +44 -0
  94. clm/layer0/model/validators/binary_validator.py +66 -0
  95. clm/layer0/model/validators/text_validator.py +82 -0
  96. clm/layer0/model/validators/validation_registry.py +49 -0
  97. clm/layer0/model/vcard.py +823 -0
  98. clm/layer0/model/vcard_ext/__init__.py +39 -0
  99. clm/layer0/model/vcard_ext/core.py +60 -0
  100. clm/layer0/model/vcard_ext/network.py +23 -0
  101. clm/layer0/model/vcard_ext/observability.py +63 -0
  102. clm/layer0/model/vcard_ext/storage.py +60 -0
  103. clm/layer0/model/vcard_ext/vendors.py +211 -0
  104. clm/layer0/model/vcard_sandwich.py +119 -0
  105. clm/layer0/model/vcard_vocabulary.py +463 -0
  106. clm/layer0/model/workflow.py +274 -0
  107. clm/layer0/narrative.py +431 -0
  108. clm/layer0/ontology/collection.py +125 -0
  109. clm/layer0/parser.py +429 -0
  110. clm/layer0/relations.py +73 -0
  111. clm/layer0/rule_evaluator.py +251 -0
  112. clm/layer0/schema/__init__.py +38 -0
  113. clm/layer0/schema/ddl.py +97 -0
  114. clm/layer0/templates/abstract.yaml +99 -0
  115. clm/layer0/templates/balanced.yaml +253 -0
  116. clm/layer0/templates/concrete.yaml +172 -0
  117. clm/layer0/type_registry.py +223 -0
  118. clm/layer0/types.py +204 -0
  119. clm/layer0/utils.py +886 -0
  120. clm/layer0/verifier_core.py +262 -0
  121. clm/layer1/__init__.py +31 -0
  122. clm/layer1/action_dispatcher.py +275 -0
  123. clm/layer1/adapter_registry.py +233 -0
  124. clm/layer1/algebra_baldwin_generators.py +192 -0
  125. clm/layer1/arrow_compiler.py +525 -0
  126. clm/layer1/batch_processor.py +152 -0
  127. clm/layer1/cel/__init__.py +27 -0
  128. clm/layer1/cel/builder.py +173 -0
  129. clm/layer1/engine.py +759 -0
  130. clm/layer1/engine_async.py +89 -0
  131. clm/layer1/eval_callback.py +49 -0
  132. clm/layer1/gate_composer.py +229 -0
  133. clm/layer1/hoare_sandwich.py +298 -0
  134. clm/layer1/identity_guard.py +348 -0
  135. clm/layer1/matrix.py +138 -0
  136. clm/layer1/neural_runtime.py +221 -0
  137. clm/layer1/operations/__init__.py +123 -0
  138. clm/layer1/operations/augment.py +156 -0
  139. clm/layer1/operations/base.py +109 -0
  140. clm/layer1/operations/builtins.py +338 -0
  141. clm/layer1/operations/dispatch.py +144 -0
  142. clm/layer1/operations/exclude.py +107 -0
  143. clm/layer1/operations/handle.py +197 -0
  144. clm/layer1/operations/identity.py +139 -0
  145. clm/layer1/operations/invert.py +66 -0
  146. clm/layer1/operations/loader.py +116 -0
  147. clm/layer1/operations/manipulators/__init__.py +23 -0
  148. clm/layer1/operations/manipulators/document.py +211 -0
  149. clm/layer1/operations/manipulators/media.py +134 -0
  150. clm/layer1/operations/manipulators/structured.py +159 -0
  151. clm/layer1/operations/manipulators/tabular.py +334 -0
  152. clm/layer1/operations/port.py +65 -0
  153. clm/layer1/operations/services.py +529 -0
  154. clm/layer1/operations/split.py +117 -0
  155. clm/layer1/operations/substitute.py +75 -0
  156. clm/layer1/petri.py +1052 -0
  157. clm/layer1/pocketflow_orchestrator.py +408 -0
  158. clm/layer1/pocketflow_scheduler.py +519 -0
  159. clm/layer1/protocols.py +197 -0
  160. clm/layer1/runtime_adapter.py +718 -0
  161. clm/layer1/runtimes/__init__.py +71 -0
  162. clm/layer1/runtimes/_generated_assertions.py +125 -0
  163. clm/layer1/runtimes/_generated_types.py +42 -0
  164. clm/layer1/runtimes/base.py +265 -0
  165. clm/layer1/runtimes/binary.py +101 -0
  166. clm/layer1/runtimes/factory.py +203 -0
  167. clm/layer1/runtimes/javascript.py +321 -0
  168. clm/layer1/runtimes/javascript_runtime.js +33 -0
  169. clm/layer1/runtimes/js_scripts/isomorphism.mjs +22 -0
  170. clm/layer1/runtimes/js_scripts/loader.mjs +52 -0
  171. clm/layer1/runtimes/lambda_calc.py +126 -0
  172. clm/layer1/runtimes/python.py +288 -0
  173. clm/layer1/runtimes/python_runtime.py +41 -0
  174. clm/layer1/runtimes/script.py +114 -0
  175. clm/layer1/sandbox.py +334 -0
  176. clm/layer1/savepoint_guard.py +136 -0
  177. clm/layer1/sparse_net.py +122 -0
  178. clm/layer1/spec_tester.py +165 -0
  179. clm/layer1/store.py +295 -0
  180. clm/layer1/test_runner.py +498 -0
  181. clm/layer1/type_inspector.py +166 -0
  182. clm/layer1/verifier.py +772 -0
  183. clm/layer1/vm.py +91 -0
  184. clm/layer2/__init__.py +78 -0
  185. clm/layer2/card_collection.py +678 -0
  186. clm/layer2/classifier.py +479 -0
  187. clm/layer2/engine/__init__.py +1 -0
  188. clm/layer2/engine/abstract_sql_engine.py +320 -0
  189. clm/layer2/engine/base.py +193 -0
  190. clm/layer2/engine/duckdb_engine.py +576 -0
  191. clm/layer2/engine/sqlite_engine.py +518 -0
  192. clm/layer2/fiber/__init__.py +31 -0
  193. clm/layer2/fiber/context.py +89 -0
  194. clm/layer2/fiber/disposable.py +163 -0
  195. clm/layer2/fiber/fiber.py +125 -0
  196. clm/layer2/fiber/hoare.py +191 -0
  197. clm/layer2/file_io.py +376 -0
  198. clm/layer2/file_registrar.py +77 -0
  199. clm/layer2/ingest.py +202 -0
  200. clm/layer2/lineage.py +322 -0
  201. clm/layer2/mcard_fs.py +262 -0
  202. clm/layer2/merkle.py +11 -0
  203. clm/layer2/mime.py +244 -0
  204. clm/layer2/mime_detector.py +245 -0
  205. clm/layer2/private_collection.py +118 -0
  206. clm/layer2/shared_store.py +11 -0
  207. clm/layer2/storage/__init__.py +190 -0
  208. clm/layer2/storage/db_bitemporal.py +141 -0
  209. clm/layer2/storage/db_driver.py +331 -0
  210. clm/layer2/storage/db_hyperlinks.py +214 -0
  211. clm/layer2/storage/db_pool.py +139 -0
  212. clm/layer2/storage/db_repository.py +229 -0
  213. clm/layer2/storage/savepoint.py +78 -0
  214. clm/layer2/storage/sqlite_wal.py +74 -0
  215. clm/layer2/tridb.py +245 -0
  216. clm/layer2/vcard_receipt.py +71 -0
  217. clm/layer2/vfs.py +17 -0
  218. clm/layer3/__init__.py +141 -0
  219. clm/layer3/agency/__init__.py +19 -0
  220. clm/layer3/agency/config.py +220 -0
  221. clm/layer3/agency/providers/__init__.py +15 -0
  222. clm/layer3/agency/providers/base.py +91 -0
  223. clm/layer3/agency/providers/mlc_llm.py +169 -0
  224. clm/layer3/agency/providers/ollama.py +203 -0
  225. clm/layer3/agency/router.py +71 -0
  226. clm/layer3/agency/runtime.py +524 -0
  227. clm/layer3/gateway.py +353 -0
  228. clm/layer3/open_interpreter_adapter.py +159 -0
  229. clm/layer3/rag/__init__.py +70 -0
  230. clm/layer3/rag/cli.py +228 -0
  231. clm/layer3/rag/config.py +153 -0
  232. clm/layer3/rag/embeddings/__init__.py +16 -0
  233. clm/layer3/rag/embeddings/base.py +79 -0
  234. clm/layer3/rag/embeddings/ollama.py +211 -0
  235. clm/layer3/rag/embeddings/vision.py +290 -0
  236. clm/layer3/rag/engine.py +276 -0
  237. clm/layer3/rag/graph/__init__.py +22 -0
  238. clm/layer3/rag/graph/community.py +198 -0
  239. clm/layer3/rag/graph/engine.py +433 -0
  240. clm/layer3/rag/graph/extractor.py +255 -0
  241. clm/layer3/rag/graph/schema.py +115 -0
  242. clm/layer3/rag/graph/store.py +641 -0
  243. clm/layer3/rag/indexer.py +333 -0
  244. clm/layer3/rag/llm_providers.json +52 -0
  245. clm/layer3/rag/semantic_versioning.py +313 -0
  246. clm/layer3/rag/vector/__init__.py +28 -0
  247. clm/layer3/rag/vector/handle_vector_store.py +749 -0
  248. clm/layer3/rag/vector/schema.py +151 -0
  249. clm/layer3/rag/vector/store.py +632 -0
  250. clm/layer3/reticulum/__init__.py +55 -0
  251. clm/layer3/reticulum/bridge.py +74 -0
  252. clm/layer3/reticulum/daemon.py +88 -0
  253. clm/layer3/reticulum/discovery.py +164 -0
  254. clm/layer3/reticulum/identity.py +107 -0
  255. clm/layer3/reticulum/media.py +148 -0
  256. clm/layer3/reticulum/transport.py +133 -0
  257. clm/layer3/satori/__init__.py +209 -0
  258. clm/layer3/satori/alpha_conversion.py +168 -0
  259. clm/layer3/satori/beta_reduction.py +359 -0
  260. clm/layer3/satori/continuation.py +38 -0
  261. clm/layer3/satori/eta_conversion.py +205 -0
  262. clm/layer3/satori/free_variables.py +163 -0
  263. clm/layer3/satori/io_effects.py +370 -0
  264. clm/layer3/satori/lambda_runtime.py +726 -0
  265. clm/layer3/satori/lambda_term.py +230 -0
  266. clm/layer3/satori/sheaf_audit.py +261 -0
  267. clm/layer3/satori/speech_act.py +279 -0
  268. clm/layer4/README.md +9 -0
  269. clm/layer4/__init__.py +67 -0
  270. clm/layer4/_sovereign_executor.py +580 -0
  271. clm/layer4/action_commands.py +719 -0
  272. clm/layer4/api.py +236 -0
  273. clm/layer4/bootstrap/__init__.py +13 -0
  274. clm/layer4/bootstrap/bootstrapper.py +118 -0
  275. clm/layer4/bootstrap/cleanup.py +44 -0
  276. clm/layer4/bootstrap/clm_hooks.py +49 -0
  277. clm/layer4/bootstrap/genesis.py +77 -0
  278. clm/layer4/bootstrap/injection.py +125 -0
  279. clm/layer4/cli.py +549 -0
  280. clm/layer4/collection_manager.py +553 -0
  281. clm/layer4/commands/__init__.py +81 -0
  282. clm/layer4/commands/action_cmd.py +42 -0
  283. clm/layer4/commands/check_cmd.py +82 -0
  284. clm/layer4/commands/envelope.py +73 -0
  285. clm/layer4/commands/evaluate_cmd.py +224 -0
  286. clm/layer4/commands/mcard_cmd.py +24 -0
  287. clm/layer4/commands/petri_cmd.py +92 -0
  288. clm/layer4/commands/tridb_cmd.py +319 -0
  289. clm/layer4/commands/version_cmd.py +27 -0
  290. clm/layer4/diff_commands.py +167 -0
  291. clm/layer4/eoa_sponsor.py +232 -0
  292. clm/layer4/events.py +69 -0
  293. clm/layer4/flux_gateway.py +133 -0
  294. clm/layer4/gateway.py +91 -0
  295. clm/layer4/loader.py +307 -0
  296. clm/layer4/mcard_commands.py +166 -0
  297. clm/layer4/membrane.py +273 -0
  298. clm/layer4/navigation.py +50 -0
  299. clm/layer4/protocol/protocol_entry_python.py +108 -0
  300. clm/layer4/protocol/python_sync.py +126 -0
  301. clm/layer4/runner.py +150 -0
  302. clm/layer4/satori.py +262 -0
  303. clm/layer4/server/python_sync_client.py +150 -0
  304. clm/layer4/server/python_sync_server.py +139 -0
  305. clm/layer4/server/service_api.py +315 -0
  306. clm/layer4/server/start_servers.py +107 -0
  307. clm/layer4/server/stop_servers.py +24 -0
  308. clm/layer4/simulated_optimization_fix.py +0 -0
  309. clm/layer4/storage.py +463 -0
  310. clm/layer4/tridb_admin.py +268 -0
  311. clm/layer4/websocket/test_ws_client.py +104 -0
  312. clm/layer4/websocket/test_ws_server.py +138 -0
  313. clm/layer4/websocket/ws_server_local.py +160 -0
  314. clm/layer5/__init__.py +51 -0
  315. clm/layer5/async_batch_writer.py +133 -0
  316. clm/layer5/learning.py +276 -0
  317. clm/layer5/telemetry_hook.py +107 -0
  318. clm/layer5/type_lattice.py +238 -0
  319. clm/py.typed +0 -0
  320. clm/schemas/__init__.py +652 -0
  321. clm/schemas/abstract_face_schema.yaml +77 -0
  322. clm/schemas/cel_schema.yaml +416 -0
  323. clm/schemas/lifecycle/__init__.py +45 -0
  324. clm/schemas/lifecycle/models.py +123 -0
  325. clm/schemas/lifecycle/service.py +364 -0
  326. clm/schemas/mcard_schema.sql +192 -0
  327. clm/schemas/mcard_vector_schema.sql +283 -0
  328. clm/schemas/mlp-context-v1.json +91 -0
  329. clm_kernel-0.0.0.dist-info/METADATA +121 -0
  330. clm_kernel-0.0.0.dist-info/RECORD +333 -0
  331. clm_kernel-0.0.0.dist-info/WHEEL +4 -0
  332. clm_kernel-0.0.0.dist-info/entry_points.txt +3 -0
  333. clm_kernel-0.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,153 @@
1
+ """CLM Domain Error Hierarchy (Sprint 175).
2
+
3
+ Stratified domain exception hierarchy for the CLM Python reference runtime.
4
+ Enforces cause chaining (raise ... from err), zero swallowed exceptions,
5
+ and machine-readable JSON-RPC serialization (to_payload()) for Satori protocol bridges.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import datetime
11
+ from typing import Any
12
+
13
+
14
+ class ClmDomainError(Exception):
15
+ """Base exception for all domain errors within CLM."""
16
+
17
+ code: int = 1000
18
+ category: str = "kernel"
19
+ is_retriable: bool = False
20
+
21
+ def __init__(
22
+ self,
23
+ message: str,
24
+ *,
25
+ details: dict[str, Any] | None = None,
26
+ cause: Exception | None = None,
27
+ is_retriable: bool = False,
28
+ ) -> None:
29
+ super().__init__(message)
30
+ self.message = message
31
+ self.details = details or {}
32
+ self.is_retriable = is_retriable
33
+ self.timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
34
+ if cause is not None:
35
+ self.__cause__ = cause
36
+
37
+ def to_payload(self) -> dict[str, Any]:
38
+ """Serialize into a machine-readable JSON-RPC error payload for Satori bridges and Maxwell's Demon."""
39
+ return {
40
+ "error": {
41
+ "code": self.code,
42
+ "category": self.category,
43
+ "name": self.__class__.__name__,
44
+ "message": self.message,
45
+ "details": self.details,
46
+ "is_retriable": self.is_retriable,
47
+ "timestamp": self.timestamp,
48
+ }
49
+ }
50
+
51
+
52
+ class ExecutionEngineError(ClmDomainError):
53
+ """Execution error within CLM runtime adapters or runner engines."""
54
+ code: int = 1500
55
+ category: str = "kernel.execution"
56
+
57
+
58
+ # -- Layer 0: Kenotic Core & Type System ---------------------------
59
+ class TypeLatticeError(ClmDomainError):
60
+ code = 1100
61
+ category = "layer0.type_lattice"
62
+
63
+
64
+ class StratificationViolationError(TypeLatticeError):
65
+ code = 1101 # Level N item referencing Level N+1 item
66
+
67
+
68
+ class AlgebraicClosedOperatorError(ClmDomainError):
69
+ code = 1200 # Split, Exclude, Augment, Substitute, Invert, Port failure
70
+ category = "layer0.algebra"
71
+
72
+
73
+ # -- Layer 1: Colored Petri Net VM & VCard Gates -------------------
74
+ class CpnVMError(ClmDomainError):
75
+ code = 2000
76
+ category = "layer1.cpn"
77
+
78
+
79
+ class TokenConservationViolationError(CpnVMError):
80
+ code = 2001 # x^T D != 0 Noetherian conservation failure
81
+
82
+
83
+ class DeadlockDetectedError(CpnVMError):
84
+ code = 2002 # Net locked with non-terminal markings
85
+
86
+
87
+ class TransitionAclDeniedError(CpnVMError):
88
+ code = 2003 # Agent DID not authorized to fire transition
89
+
90
+
91
+ class VCardGateError(ClmDomainError):
92
+ code = 2100
93
+ category = "layer1.vcard"
94
+
95
+
96
+ class PreconditionViolationError(VCardGateError):
97
+ code = 2101 # {P} failed before PCard execution
98
+
99
+
100
+ class PostconditionViolationError(VCardGateError):
101
+ code = 2102 # {Q} failed after PCard execution
102
+
103
+
104
+ class VCardEvaluationFaultError(VCardGateError):
105
+ code = 2103 # Unexpected system/IO fault during gate execution
106
+
107
+
108
+ # -- Layer 2: Storage, CAS & Merkle DAG ----------------------------
109
+ class StorageEngineError(ClmDomainError):
110
+ code = 3000
111
+ category = "layer2.storage"
112
+
113
+
114
+ class ContentHashMismatchError(StorageEngineError):
115
+ code = 3001 # Computed BLAKE3/SHA-256 does not match MCard key
116
+
117
+
118
+ class HandleNotFoundError(StorageEngineError):
119
+ code = 3002
120
+
121
+
122
+ class DatabaseLockTimeoutError(StorageEngineError):
123
+ code = 3003
124
+
125
+
126
+ class ManifestParseError(StorageEngineError):
127
+ code = 3004
128
+
129
+
130
+ # -- Layer 3: Identity, Auth & Network Mesh -------------------------
131
+ class IdentityAuthError(ClmDomainError):
132
+ code = 4000
133
+ category = "layer3.auth"
134
+
135
+
136
+ class InvalidDidSignatureError(IdentityAuthError):
137
+ code = 4001
138
+
139
+
140
+ class PeerUnreachableError(ClmDomainError):
141
+ code = 4100
142
+ category = "layer3.network"
143
+
144
+
145
+ # -- Layer 4: CEL, Dispatch & Surface ------------------------------
146
+ class CelEvaluationError(ClmDomainError):
147
+ code = 5000
148
+ category = "layer4.cel"
149
+
150
+
151
+ class OperationNotFoundError(ClmDomainError):
152
+ code = 5100
153
+ category = "layer4.dispatch"
@@ -0,0 +1,331 @@
1
+ """
2
+ Token Arithmetics Governance Computation Module.
3
+
4
+ Pure-function module containing the quantitative governance metrics defined in:
5
+ - Architecture §1.7: Inherent Governance
6
+ - Architecture §03: Token Arithmetics — Governance Through Possibility Space Assessment
7
+ - Specifications §04 §2.5: Type-Based Possibility Arithmetics
8
+
9
+ All functions are side-effect-free and operate exclusively on primitive values.
10
+ No database access, no I/O — just math.
11
+
12
+ Metrics computed:
13
+ - M (Possibility Magnitude): |B|^|A| — total combinatorial space
14
+ - N (Governance Narrowing): 1 - |B'|^|A'| / |B|^|A| — policy restrictiveness
15
+ - E (Epiplexity Yield): S_T / M — structured knowledge per possibility
16
+ - Pi (Product Dependency Count): number of concurrent precondition evaluations
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import logging
22
+ from dataclasses import dataclass
23
+ from typing import Any
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class GovernanceTelemetry:
30
+ """Immutable governance telemetry triple (+ product dependency count).
31
+
32
+ Embedded as structured metadata within VCard postconditions.
33
+ """
34
+
35
+ possibility_magnitude: float | None = None
36
+ governance_narrowing: float | None = None
37
+ epiplexity_yield: float | None = None
38
+ product_dependency_count: int | None = None
39
+
40
+ def to_dict(self) -> dict[str, Any]:
41
+ """Serialize to a plain dict for VCard metadata embedding."""
42
+ result: dict[str, Any] = {}
43
+ if self.possibility_magnitude is not None:
44
+ result["M"] = self.possibility_magnitude
45
+ if self.governance_narrowing is not None:
46
+ result["N"] = self.governance_narrowing
47
+ if self.epiplexity_yield is not None:
48
+ result["E"] = self.epiplexity_yield
49
+ if self.product_dependency_count is not None:
50
+ result["Pi"] = self.product_dependency_count
51
+ return result
52
+
53
+ @classmethod
54
+ def from_dict(cls, data: dict[str, Any]) -> GovernanceTelemetry:
55
+ """Deserialize from a plain dict."""
56
+ return cls(
57
+ possibility_magnitude=data.get("M"),
58
+ governance_narrowing=data.get("N"),
59
+ epiplexity_yield=data.get("E"),
60
+ product_dependency_count=data.get("Pi"),
61
+ )
62
+
63
+
64
+ # ---------------------------------------------------------------------------
65
+ # Core metric computations
66
+ # ---------------------------------------------------------------------------
67
+
68
+
69
+ def compute_possibility_magnitude(inputs_count: int, outputs_count: int) -> float:
70
+ """Compute Possibility Magnitude M = |B|^|A|.
71
+
72
+ Args:
73
+ inputs_count: |A| — number of input dimensions (Categorical Types).
74
+ outputs_count: |B| — number of output options (Categorical Types).
75
+
76
+ Returns:
77
+ The total combinatorial space as a float.
78
+ Returns 1.0 when both counts are 0 (trivial identity transition).
79
+ """
80
+ if inputs_count < 0 or outputs_count < 0:
81
+ raise ValueError(
82
+ f"Type counts must be non-negative: inputs={inputs_count}, outputs={outputs_count}"
83
+ )
84
+ if inputs_count == 0 and outputs_count == 0:
85
+ return 1.0
86
+ if outputs_count == 0:
87
+ return 0.0
88
+ return float(outputs_count**inputs_count)
89
+
90
+
91
+ def compute_governance_narrowing(m_full: float, m_admitted: float) -> float:
92
+ """Compute Governance Narrowing N = 1 - M_admitted / M_full.
93
+
94
+ Args:
95
+ m_full: |B|^|A| — full possibility magnitude before VCard constraints.
96
+ m_admitted: |B'|^|A'| — admitted possibility magnitude after VCard constraints.
97
+
98
+ Returns:
99
+ Fraction of the possibility space excluded by governance policy.
100
+ Range: [0.0, 1.0] where 1.0 means total restriction, 0.0 means no restriction.
101
+ """
102
+ if m_full <= 0:
103
+ return 0.0
104
+ if m_admitted < 0:
105
+ raise ValueError(f"Admitted magnitude must be non-negative: {m_admitted}")
106
+ ratio = m_admitted / m_full
107
+ # Clamp to [0.0, 1.0] to handle floating-point edge cases
108
+ return max(0.0, min(1.0, 1.0 - ratio))
109
+
110
+
111
+ def compute_epiplexity_yield(structured_knowledge: float, magnitude: float) -> float:
112
+ """Compute Epiplexity Yield E = S_T / M.
113
+
114
+ Uses alignment_score as the proxy for S_T (semantic vector confidence score).
115
+
116
+ Args:
117
+ structured_knowledge: S_T — semantic confidence score (e.g., alignment_score).
118
+ magnitude: M — possibility magnitude computed during PREP.
119
+
120
+ Returns:
121
+ Ratio of structured knowledge extracted per possibility explored.
122
+ Returns 0.0 when magnitude is 0 (no possibilities to explore).
123
+ """
124
+ if magnitude <= 0:
125
+ return 0.0
126
+ return structured_knowledge / magnitude
127
+
128
+
129
+ # ---------------------------------------------------------------------------
130
+ # CLM spec extraction helpers
131
+ # ---------------------------------------------------------------------------
132
+
133
+
134
+ def extract_type_counts_from_clm(clm_spec: dict[str, Any]) -> tuple[int, int]:
135
+ """Extract |A| and |B| from a parsed CLM abstract_spec.
136
+
137
+ Looks for typed inputs/outputs in the CLM YAML structure:
138
+ - abstract_spec.inputs → list of input type descriptors → |A|
139
+ - abstract_spec.outputs → list of output type descriptors → |B|
140
+
141
+ Args:
142
+ clm_spec: Parsed CLM YAML as a dict (the full PCard content).
143
+
144
+ Returns:
145
+ Tuple of (inputs_count, outputs_count). Returns (0, 0) if the CLM
146
+ spec does not contain typed inputs/outputs (graceful degradation).
147
+ """
148
+ abstract = clm_spec.get("abstract_spec", {})
149
+ if not abstract:
150
+ # Try alternative key names
151
+ abstract = clm_spec.get("abstract", {})
152
+
153
+ inputs = abstract.get("inputs", [])
154
+ outputs = abstract.get("outputs", [])
155
+
156
+ # Handle both list and dict formats
157
+ inputs_count = len(inputs) if isinstance(inputs, list | dict) else 0
158
+ outputs_count = len(outputs) if isinstance(outputs, list | dict) else 0
159
+
160
+ return (inputs_count, outputs_count)
161
+
162
+
163
+ def extract_admitted_counts_from_vcard(
164
+ clm_spec: dict[str, Any],
165
+ vcard_constraints: dict[str, Any] | None,
166
+ ) -> tuple[int, int]:
167
+ """Extract |A'| and |B'| — the admitted subsets after VCard policy application.
168
+
169
+ The admitted counts are derived by intersecting the CLM's full type space
170
+ with the VCard precondition constraints. If no constraints are specified,
171
+ the admitted space equals the full space (N = 0, no narrowing).
172
+
173
+ Args:
174
+ clm_spec: Parsed CLM YAML.
175
+ vcard_constraints: VCard precondition constraints (may be None).
176
+
177
+ Returns:
178
+ Tuple of (admitted_inputs, admitted_outputs).
179
+ """
180
+ full_a, full_b = extract_type_counts_from_clm(clm_spec)
181
+
182
+ if not vcard_constraints:
183
+ return (full_a, full_b)
184
+
185
+ # Check for explicit admitted type lists in VCard constraints
186
+ admitted_inputs = vcard_constraints.get("admitted_inputs")
187
+ admitted_outputs = vcard_constraints.get("admitted_outputs")
188
+
189
+ # If constraints specify admitted subsets, use their counts
190
+ a_prime = (
191
+ len(admitted_inputs) if isinstance(admitted_inputs, list | dict) else full_a
192
+ )
193
+ b_prime = (
194
+ len(admitted_outputs) if isinstance(admitted_outputs, list | dict) else full_b
195
+ )
196
+
197
+ # Check for exclusion lists (alternative constraint format)
198
+ excluded_inputs = vcard_constraints.get("excluded_inputs")
199
+ excluded_outputs = vcard_constraints.get("excluded_outputs")
200
+
201
+ if isinstance(excluded_inputs, list) and admitted_inputs is None:
202
+ a_prime = max(0, full_a - len(excluded_inputs))
203
+ if isinstance(excluded_outputs, list) and admitted_outputs is None:
204
+ b_prime = max(0, full_b - len(excluded_outputs))
205
+
206
+ return (a_prime, b_prime)
207
+
208
+
209
+ def count_product_dependencies(clm_spec: dict[str, Any]) -> int:
210
+ """Count the Product Dependency Count (Pi).
211
+
212
+ Pi = number of concurrent precondition evaluations required for
213
+ transition firing. Derived from the CLM's preconditions list.
214
+
215
+ Args:
216
+ clm_spec: Parsed CLM YAML.
217
+
218
+ Returns:
219
+ Number of precondition evaluations (minimum 1 for any valid CLM).
220
+ """
221
+ abstract = clm_spec.get("abstract_spec", {}) or clm_spec.get("abstract", {})
222
+ preconditions = abstract.get("preconditions", [])
223
+
224
+ if isinstance(preconditions, list):
225
+ return max(1, len(preconditions))
226
+ if isinstance(preconditions, dict):
227
+ return max(1, len(preconditions))
228
+ return 1
229
+
230
+
231
+ # ---------------------------------------------------------------------------
232
+ # High-level orchestration
233
+ # ---------------------------------------------------------------------------
234
+
235
+
236
+ def compute_prep_governance(
237
+ clm_spec: dict[str, Any],
238
+ vcard_constraints: dict[str, Any] | None = None,
239
+ ) -> GovernanceTelemetry:
240
+ """Compute governance metrics available during the PREP phase.
241
+
242
+ Called after CLM verification succeeds. Computes M, N, and Pi.
243
+ E (Epiplexity Yield) is deferred to the POST phase.
244
+
245
+ Args:
246
+ clm_spec: Parsed CLM YAML spec.
247
+ vcard_constraints: Optional VCard precondition constraints.
248
+
249
+ Returns:
250
+ GovernanceTelemetry with M, N, Pi populated (E = None).
251
+ """
252
+ try:
253
+ a, b = extract_type_counts_from_clm(clm_spec)
254
+
255
+ if a == 0 and b == 0:
256
+ # CLM spec lacks typed inputs/outputs → graceful degradation
257
+ logger.debug(
258
+ "[GOVERNANCE] CLM spec has no typed inputs/outputs; "
259
+ "governance metrics set to None."
260
+ )
261
+ return GovernanceTelemetry()
262
+
263
+ m_full = compute_possibility_magnitude(a, b)
264
+
265
+ a_prime, b_prime = extract_admitted_counts_from_vcard(
266
+ clm_spec, vcard_constraints
267
+ )
268
+ m_admitted = compute_possibility_magnitude(a_prime, b_prime)
269
+
270
+ narrowing = compute_governance_narrowing(m_full, m_admitted)
271
+ pi = count_product_dependencies(clm_spec)
272
+
273
+ logger.info(
274
+ f"[GOVERNANCE] PREP metrics: M={m_full}, N={narrowing:.4f}, Pi={pi} "
275
+ f"(|A|={a}, |B|={b}, |A'|={a_prime}, |B'|={b_prime})"
276
+ )
277
+
278
+ return GovernanceTelemetry(
279
+ possibility_magnitude=m_full,
280
+ governance_narrowing=narrowing,
281
+ product_dependency_count=pi,
282
+ )
283
+
284
+ except Exception:
285
+ logger.warning(
286
+ "[GOVERNANCE] Failed to compute PREP governance metrics", exc_info=True
287
+ )
288
+ return GovernanceTelemetry()
289
+
290
+
291
+ def compute_post_governance(
292
+ prep_telemetry: GovernanceTelemetry,
293
+ alignment_score: float | None,
294
+ ) -> GovernanceTelemetry:
295
+ """Compute the final governance telemetry including Epiplexity Yield.
296
+
297
+ Called during the POST phase after execution and alignment scoring.
298
+ Uses alignment_score as the proxy for S_T (semantic confidence).
299
+
300
+ Args:
301
+ prep_telemetry: GovernanceTelemetry from the PREP phase.
302
+ alignment_score: The directional alignment score (proxy for S_T).
303
+
304
+ Returns:
305
+ Complete GovernanceTelemetry with all four metrics.
306
+ """
307
+ if alignment_score is None or prep_telemetry.possibility_magnitude is None:
308
+ return prep_telemetry
309
+
310
+ try:
311
+ epiplexity = compute_epiplexity_yield(
312
+ alignment_score, prep_telemetry.possibility_magnitude
313
+ )
314
+
315
+ logger.info(
316
+ f"[GOVERNANCE] POST metrics: E={epiplexity:.6f} "
317
+ f"(S_T={alignment_score}, M={prep_telemetry.possibility_magnitude})"
318
+ )
319
+
320
+ return GovernanceTelemetry(
321
+ possibility_magnitude=prep_telemetry.possibility_magnitude,
322
+ governance_narrowing=prep_telemetry.governance_narrowing,
323
+ epiplexity_yield=epiplexity,
324
+ product_dependency_count=prep_telemetry.product_dependency_count,
325
+ )
326
+
327
+ except Exception:
328
+ logger.warning(
329
+ "[GOVERNANCE] Failed to compute POST governance metrics", exc_info=True
330
+ )
331
+ return prep_telemetry
@@ -0,0 +1,41 @@
1
+ """RAII Resource Guards for Process Descriptors and Temporary Storage (Sprint 178).
2
+
3
+ Ensures deterministic cleanup of redirected file descriptors and temporary directories.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import shutil
9
+ import sys
10
+ import tempfile
11
+ from contextlib import contextmanager
12
+ from typing import Any, Generator
13
+
14
+
15
+ @contextmanager
16
+ def fd_redirect_guard(
17
+ stdout: Any | None = None,
18
+ stderr: Any | None = None,
19
+ ) -> Generator[None, None, None]:
20
+ """RAII guard that redirects stdout and stderr, guaranteeing restoration on exit."""
21
+ old_stdout = sys.stdout
22
+ old_stderr = sys.stderr
23
+ try:
24
+ if stdout is not None:
25
+ sys.stdout = stdout
26
+ if stderr is not None:
27
+ sys.stderr = stderr
28
+ yield
29
+ finally:
30
+ sys.stdout = old_stdout
31
+ sys.stderr = old_stderr
32
+
33
+
34
+ @contextmanager
35
+ def temp_dir_guard(prefix: str = "clm_tmp_") -> Generator[str, None, None]:
36
+ """RAII temporary directory manager with guaranteed recursive cleanup even on exceptions."""
37
+ tmp_path = tempfile.mkdtemp(prefix=prefix)
38
+ try:
39
+ yield tmp_path
40
+ finally:
41
+ shutil.rmtree(tmp_path, ignore_errors=True)