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,156 @@
1
+ """CLM Manifest IO helpers (Sprint 133.1).
2
+
3
+ Extracted from ``algebra.py``. Handles loading, normalizing, and parsing
4
+ CLM YAML manifest files.
5
+ """
6
+ import os
7
+ import subprocess
8
+ import sys
9
+
10
+ import yaml
11
+
12
+ from clm.layer0.utils import HASH_PREFIX, clm_hash_string
13
+
14
+ from .utils import resolve_clm_path
15
+
16
+
17
+ def load_normalized_manifest_str(clm_root: str, clm_file: str) -> str:
18
+ """Loads and normalizes the contents of a CLM manifest file as a string."""
19
+ clm_file = resolve_clm_path(clm_root, clm_file)
20
+ normalizer_py = os.path.join(clm_root, "computable_knowledge/Concrete/layer5_system/bootstrap/layer2_storage/clm_normalize_syntax.py")
21
+ if os.path.exists(normalizer_py):
22
+ proc = subprocess.Popen([sys.executable, normalizer_py, clm_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
23
+ stdout_data, _ = proc.communicate()
24
+ if proc.returncode == 0:
25
+ temp_path = stdout_data.strip()
26
+ if os.path.exists(temp_path):
27
+ try:
28
+ with open(temp_path, encoding='utf-8') as f:
29
+ norm_content = f.read()
30
+ os.remove(temp_path)
31
+ return norm_content
32
+ except Exception:
33
+ pass
34
+ with open(clm_file, encoding='utf-8') as f:
35
+ return f.read()
36
+
37
+
38
+ def load_normalized_manifest(clm_root: str, clm_file: str) -> dict:
39
+ """Loads and normalizes a CLM manifest, parsing it as a dictionary."""
40
+ clm_file = resolve_clm_path(clm_root, clm_file)
41
+ content_str = load_normalized_manifest_str(clm_root, clm_file)
42
+ return yaml.safe_load(content_str)
43
+
44
+
45
+ def compute_stripped_file_hash_py(filepath: str) -> str:
46
+ """Computes SHA-256 of a file after stripping trailing CR/LF."""
47
+ if not os.path.exists(filepath):
48
+ return f"{HASH_PREFIX}unknown"
49
+ with open(filepath, encoding='utf-8') as f:
50
+ content = f.read()
51
+ trimmed = content.rstrip('\r\n')
52
+ return clm_hash_string(trimmed)
53
+
54
+
55
+ def execute_pcard_py(clm_root: str, clm_file: str, payload: str) -> str:
56
+ """Executes a PCard in a nested sandbox."""
57
+ engine_py = os.path.join(clm_root, "kernel/scripts/clm_runner.py")
58
+ if not os.path.exists(engine_py):
59
+ engine_py = __file__
60
+
61
+ cmd = [sys.executable, engine_py, "evaluate", clm_file, payload]
62
+ env = os.environ.copy()
63
+ env["CLM_PAYLOAD"] = payload
64
+ env["CLM_NESTED_EXEC"] = "1"
65
+ env["CLM_ZERO_FS"] = "true"
66
+ env["CLM_SKIP_GRAMMAR"] = "1"
67
+
68
+ proc = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
69
+ stdout_data, _ = proc.communicate()
70
+ if proc.returncode == 0:
71
+ stdout_str = stdout_data
72
+ idx = stdout_str.find("[POST] V_post:")
73
+ if idx != -1:
74
+ stdout_str = stdout_str[:idx]
75
+ return stdout_str.strip()
76
+ else:
77
+ return ""
78
+
79
+
80
+ def parse_json_or_yaml_py(s: str):
81
+ """Parses a string as JSON or YAML, falling back to YAML if JSON fails."""
82
+ s_trimmed = s.strip()
83
+ if not s_trimmed:
84
+ return None
85
+ try:
86
+ import json
87
+ return json.loads(s_trimmed)
88
+ except Exception:
89
+ pass
90
+ try:
91
+ return yaml.safe_load(s_trimmed)
92
+ except Exception:
93
+ pass
94
+ raise Exception("Not valid JSON or YAML")
95
+
96
+
97
+ def canonical_value_py(val):
98
+ """Recursively sorts dictionary keys to produce canonical representation."""
99
+ if isinstance(val, dict):
100
+ sorted_keys = sorted(val.keys())
101
+ return {k: canonical_value_py(val[k]) for k in sorted_keys}
102
+ elif isinstance(val, list):
103
+ return [canonical_value_py(item) for item in val]
104
+ else:
105
+ return val
106
+
107
+
108
+ def clean_data_py(val):
109
+ """Recursively removes metadata keys to allow comparison of core data."""
110
+ if isinstance(val, dict):
111
+ cleaned = {}
112
+ for k, v in val.items():
113
+ if k in (
114
+ "timestamp", "g_time", "run_id", "previous_hash", "changed_at",
115
+ "created_at", "updated_at", "witness_trail", "performance_differential",
116
+ "agent_did", "uuid", "g_time_note", "genesis_hash", "genesis_note"
117
+ ):
118
+ continue
119
+ cleaned[k] = clean_data_py(v)
120
+ return cleaned
121
+ elif isinstance(val, list):
122
+ import json
123
+ cleaned_list = [clean_data_py(item) for item in val]
124
+ cleaned_list.sort(key=lambda x: json.dumps(canonical_value_py(x), sort_keys=True, separators=(',', ':')))
125
+ return cleaned_list
126
+ else:
127
+ return val
128
+
129
+
130
+ def compare_numerical_py(s_a: str, s_b: str) -> bool:
131
+ """Compares two numerical strings for approximate equivalence."""
132
+ try:
133
+ a = float(s_a.strip())
134
+ b = float(s_b.strip())
135
+ return abs(a - b) <= 1e-6
136
+ except Exception:
137
+ return False
138
+
139
+
140
+ def check_content_equivalent_py(clm_root: str, hash_a: str, hash_b: str) -> bool:
141
+ """Checks if two hashes resolve to the exact same content in the CLM database."""
142
+ if hash_a == hash_b:
143
+ return True
144
+ from .db import CLMDB
145
+ db = CLMDB(clm_root)
146
+ sql = "SELECT content FROM card WHERE hash = ?;"
147
+ try:
148
+ res_a = db.execute("content_memory", sql, [hash_a])
149
+ res_b = db.execute("content_memory", sql, [hash_b])
150
+ content_a = res_a.strip() if res_a else ""
151
+ content_b = res_b.strip() if res_b else ""
152
+ if content_a and content_b:
153
+ return content_a == content_b
154
+ except Exception:
155
+ pass
156
+ return False
@@ -0,0 +1,481 @@
1
+ """CLM Assembler - Dynamic assembly of CLM components using MCard Collections (Layer 0).
2
+
3
+ Part of Phase 7 (Sprint 383: Layer 0 Kenotic Core & Parser Unification).
4
+ Provides functionality to dynamically assemble complete CLM specifications
5
+ from individual Abstract, Concrete, and Balanced components stored as MCards.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from dataclasses import dataclass
12
+ from datetime import datetime, timezone
13
+ from typing import Any
14
+
15
+ import yaml
16
+
17
+ try:
18
+ from clm.layer0.model.card import MCard
19
+ except ImportError:
20
+ from clm.layer0.mcard import MCard
21
+
22
+ from clm.layer0.loader import YAMLTemplateLoader
23
+
24
+
25
+ @dataclass
26
+ class CLMComponent:
27
+ """Individual CLM component (Abstract, Concrete, or Balanced)"""
28
+
29
+ dimension: str # 'abstract', 'concrete', or 'balanced'
30
+ name: str
31
+ content: dict[str, Any]
32
+ mcard_hash: str
33
+ version: str = "1.0.0"
34
+ dependencies: list[str] | None = None # Hashes of dependent components
35
+
36
+
37
+ @dataclass
38
+ class AssembledCLM:
39
+ """Complete assembled CLM specification"""
40
+
41
+ name: str
42
+ abstract: CLMComponent
43
+ concrete: CLMComponent
44
+ balanced: CLMComponent
45
+ assembly_hash: str # Hash of the assembled CLM MCard
46
+ created_at: datetime
47
+ validation_result: ValidationResult | None = None
48
+
49
+
50
+ @dataclass
51
+ class ValidationResult:
52
+ """Result of CLM assembly validation"""
53
+
54
+ is_valid: bool
55
+ errors: list[str]
56
+ warnings: list[str]
57
+ consistency_checks: dict[str, bool]
58
+
59
+
60
+ class CLMAssembler:
61
+ """Assembler for dynamic CLM construction using MCard Collections.
62
+
63
+ This class enables:
64
+ - Loading CLM components from MCard storage
65
+ - Assembling complete CLM specifications
66
+ - Validating assembled CLMs
67
+ - Storing and retrieving assembled CLMs
68
+ - Managing component dependencies
69
+ """
70
+
71
+ def __init__(
72
+ self, storage_collection=None, template_loader: YAMLTemplateLoader | None = None
73
+ ):
74
+ self.logger = logging.getLogger(__name__)
75
+ self.collection = storage_collection
76
+ self.template_loader = template_loader or YAMLTemplateLoader(storage_collection)
77
+ self.component_cache: dict[str, CLMComponent] = {}
78
+ self.assembly_cache: dict[str, AssembledCLM] = {}
79
+
80
+ self.logger.info("CLM Assembler initialized")
81
+
82
+ def load_component_from_mcard(self, component_hash: str) -> CLMComponent:
83
+ """Load a CLM component from MCard storage.
84
+
85
+ Args:
86
+ component_hash: Hash of the component MCard
87
+
88
+ Returns:
89
+ CLMComponent object
90
+ """
91
+ if component_hash in self.component_cache:
92
+ return self.component_cache[component_hash]
93
+
94
+ try:
95
+ component_mcard = self.collection.get(component_hash)
96
+ if not component_mcard:
97
+ raise ValueError(f"Component MCard not found: {component_hash}")
98
+
99
+ content_bytes = component_mcard.get_content()
100
+ component_yaml = (
101
+ content_bytes.decode("utf-8")
102
+ if isinstance(content_bytes, bytes)
103
+ else str(content_bytes)
104
+ )
105
+ component_data = yaml.safe_load(component_yaml)
106
+
107
+ metadata = component_data.get("metadata", {})
108
+ content = component_data.get("template", component_data.get("content", {}))
109
+
110
+ component = CLMComponent(
111
+ dimension=metadata.get("dimension", "unknown"),
112
+ name=metadata.get("name", "unknown"),
113
+ content=content,
114
+ mcard_hash=component_hash,
115
+ version=metadata.get("version", "1.0.0"),
116
+ dependencies=metadata.get("dependencies", []),
117
+ )
118
+
119
+ self.component_cache[component_hash] = component
120
+
121
+ self.logger.info(
122
+ f"Loaded component {component.name} ({component.dimension}) from MCard"
123
+ )
124
+
125
+ return component
126
+
127
+ except (
128
+ yaml.YAMLError,
129
+ ValueError,
130
+ TypeError,
131
+ KeyError,
132
+ UnicodeDecodeError,
133
+ ) as e:
134
+ self.logger.error(
135
+ f"Failed to load component from MCard {component_hash}: {str(e)}",
136
+ exc_info=True,
137
+ )
138
+ raise ValueError(f"Component loading failed: {str(e)}") from e
139
+
140
+ def create_component_from_template(
141
+ self,
142
+ dimension: str,
143
+ name: str,
144
+ template_data: dict[str, Any],
145
+ dependencies: list[str] | None = None,
146
+ ) -> CLMComponent:
147
+ """Create a CLM component from template data.
148
+
149
+ Args:
150
+ dimension: CLM dimension ('abstract', 'concrete', or 'balanced')
151
+ name: Component name
152
+ template_data: Template content
153
+ dependencies: List of dependent component hashes
154
+
155
+ Returns:
156
+ CLMComponent object
157
+ """
158
+ try:
159
+ component_metadata = {
160
+ "type": "CLM_Component",
161
+ "dimension": dimension,
162
+ "name": name,
163
+ "version": "1.0.0",
164
+ "dependencies": dependencies or [],
165
+ "created_at": datetime.now(timezone.utc).isoformat(),
166
+ }
167
+
168
+ component_data = {"metadata": component_metadata, "content": template_data}
169
+ component_yaml = yaml.safe_dump(component_data, default_flow_style=False)
170
+ component_mcard = MCard(component_yaml)
171
+ component_hash = self.collection.add(component_mcard)
172
+
173
+ component = CLMComponent(
174
+ dimension=dimension,
175
+ name=name,
176
+ content=template_data,
177
+ mcard_hash=component_hash,
178
+ version="1.0.0",
179
+ dependencies=dependencies or [],
180
+ )
181
+
182
+ self.component_cache[component_hash] = component
183
+
184
+ self.logger.info(
185
+ f"Created component {name} ({dimension}) as MCard: {component_hash}"
186
+ )
187
+
188
+ return component
189
+
190
+ except (yaml.YAMLError, ValueError, TypeError, KeyError) as e:
191
+ self.logger.error(
192
+ f"Failed to create component from template: {str(e)}", exc_info=True
193
+ )
194
+ raise ValueError(f"Component creation failed: {str(e)}") from e
195
+
196
+ def assemble_clm(
197
+ self,
198
+ abstract_hash: str,
199
+ concrete_hash: str,
200
+ balanced_hash: str,
201
+ name: str | None = None,
202
+ ) -> AssembledCLM:
203
+ """Assemble a complete CLM from individual components.
204
+
205
+ Args:
206
+ abstract_hash: Hash of abstract component
207
+ concrete_hash: Hash of concrete component
208
+ balanced_hash: Hash of balanced component
209
+ name: Optional name for the assembled CLM
210
+
211
+ Returns:
212
+ AssembledCLM object
213
+ """
214
+ try:
215
+ abstract = self.load_component_from_mcard(abstract_hash)
216
+ concrete = self.load_component_from_mcard(concrete_hash)
217
+ balanced = self.load_component_from_mcard(balanced_hash)
218
+
219
+ if abstract.dimension != "abstract":
220
+ raise ValueError(
221
+ f"Expected abstract component, got {abstract.dimension}"
222
+ )
223
+ if concrete.dimension != "concrete":
224
+ raise ValueError(
225
+ f"Expected concrete component, got {concrete.dimension}"
226
+ )
227
+ if balanced.dimension != "balanced":
228
+ raise ValueError(
229
+ f"Expected balanced component, got {balanced.dimension}"
230
+ )
231
+
232
+ if not name:
233
+ name = f"CLM_{abstract.name}_{concrete.name}_{balanced.name}"
234
+
235
+ validation_result = self._validate_clm_assembly(
236
+ abstract, concrete, balanced
237
+ )
238
+
239
+ assembled_data = {
240
+ "type": "Assembled_CLM",
241
+ "name": name,
242
+ "version": "1.0.0",
243
+ "created_at": datetime.now(timezone.utc).isoformat(),
244
+ "components": {
245
+ "abstract": {
246
+ "name": abstract.name,
247
+ "hash": abstract_hash,
248
+ "version": abstract.version,
249
+ },
250
+ "concrete": {
251
+ "name": concrete.name,
252
+ "hash": concrete_hash,
253
+ "version": concrete.version,
254
+ },
255
+ "balanced": {
256
+ "name": balanced.name,
257
+ "hash": balanced_hash,
258
+ "version": balanced.version,
259
+ },
260
+ },
261
+ "content": {
262
+ "abstract": abstract.content,
263
+ "concrete": concrete.content,
264
+ "balanced": balanced.content,
265
+ },
266
+ "validation": {
267
+ "is_valid": validation_result.is_valid,
268
+ "errors": validation_result.errors,
269
+ "warnings": validation_result.warnings,
270
+ "consistency_checks": validation_result.consistency_checks,
271
+ },
272
+ }
273
+
274
+ assembled_yaml = yaml.safe_dump(assembled_data, default_flow_style=False)
275
+ assembled_mcard = MCard(assembled_yaml)
276
+ assembly_hash = self.collection.add(assembled_mcard)
277
+
278
+ assembled_clm = AssembledCLM(
279
+ name=name,
280
+ abstract=abstract,
281
+ concrete=concrete,
282
+ balanced=balanced,
283
+ assembly_hash=assembly_hash,
284
+ created_at=datetime.now(timezone.utc),
285
+ validation_result=validation_result,
286
+ )
287
+
288
+ self.assembly_cache[assembly_hash] = assembled_clm
289
+
290
+ self.logger.info(
291
+ f"Assembled CLM {name}: {'VALID' if validation_result.is_valid else 'INVALID'}"
292
+ )
293
+
294
+ return assembled_clm
295
+
296
+ except (yaml.YAMLError, ValueError, TypeError, KeyError) as e:
297
+ self.logger.error(f"Failed to assemble CLM: {str(e)}", exc_info=True)
298
+ raise ValueError(f"CLM assembly failed: {str(e)}") from e
299
+
300
+ def load_assembled_clm(self, assembly_hash: str) -> AssembledCLM:
301
+ """Load an assembled CLM from MCard storage.
302
+
303
+ Args:
304
+ assembly_hash: Hash of the assembled CLM MCard
305
+
306
+ Returns:
307
+ AssembledCLM object
308
+ """
309
+ if assembly_hash in self.assembly_cache:
310
+ return self.assembly_cache[assembly_hash]
311
+
312
+ try:
313
+ assembled_mcard = self.collection.get(assembly_hash)
314
+ if not assembled_mcard:
315
+ raise ValueError(f"Assembled CLM not found: {assembly_hash}")
316
+
317
+ content_bytes = assembled_mcard.get_content()
318
+ assembled_yaml = (
319
+ content_bytes.decode("utf-8")
320
+ if isinstance(content_bytes, bytes)
321
+ else str(content_bytes)
322
+ )
323
+ assembled_data = yaml.safe_load(assembled_yaml)
324
+
325
+ components = assembled_data.get("components", {})
326
+ abstract_info = components.get("abstract", {})
327
+ concrete_info = components.get("concrete", {})
328
+ balanced_info = components.get("balanced", {})
329
+
330
+ abstract = self.load_component_from_mcard(abstract_info["hash"])
331
+ concrete = self.load_component_from_mcard(concrete_info["hash"])
332
+ balanced = self.load_component_from_mcard(balanced_info["hash"])
333
+
334
+ validation_data = assembled_data.get("validation", {})
335
+ validation_result = ValidationResult(
336
+ is_valid=validation_data.get("is_valid", True),
337
+ errors=validation_data.get("errors", []),
338
+ warnings=validation_data.get("warnings", []),
339
+ consistency_checks=validation_data.get("consistency_checks", {}),
340
+ )
341
+
342
+ created_at_str = assembled_data.get(
343
+ "created_at", datetime.now(timezone.utc).isoformat()
344
+ )
345
+ assembled_clm = AssembledCLM(
346
+ name=assembled_data.get("name", "unknown"),
347
+ abstract=abstract,
348
+ concrete=concrete,
349
+ balanced=balanced,
350
+ assembly_hash=assembly_hash,
351
+ created_at=datetime.fromisoformat(created_at_str),
352
+ validation_result=validation_result,
353
+ )
354
+
355
+ self.assembly_cache[assembly_hash] = assembled_clm
356
+
357
+ self.logger.info(f"Loaded assembled CLM {assembled_clm.name} from MCard")
358
+
359
+ return assembled_clm
360
+
361
+ except (
362
+ yaml.YAMLError,
363
+ ValueError,
364
+ TypeError,
365
+ KeyError,
366
+ UnicodeDecodeError,
367
+ ) as e:
368
+ self.logger.error(
369
+ f"Failed to load assembled CLM {assembly_hash}: {str(e)}", exc_info=True
370
+ )
371
+ raise ValueError(f"Assembled CLM loading failed: {str(e)}") from e
372
+
373
+ def find_compatible_components(
374
+ self, dimension: str, filters: dict[str, Any] | None = None
375
+ ) -> list[CLMComponent]:
376
+ """Find compatible components for a given dimension."""
377
+ try:
378
+ search_term = f"CLM_Component_{dimension}"
379
+ if filters and "name" in filters:
380
+ search_term = f"{search_term}_{filters['name']}"
381
+
382
+ found_cards = self.collection.search_by_string(search_term)
383
+ components = []
384
+
385
+ for card in found_cards.items:
386
+ try:
387
+ component = self.load_component_from_mcard(card.hash)
388
+
389
+ if filters:
390
+ match = True
391
+ for key, value in filters.items():
392
+ if key == "name" and component.name != value or key == "version" and component.version != value:
393
+ match = False
394
+ break
395
+ if not match:
396
+ continue
397
+
398
+ components.append(component)
399
+
400
+ except (ValueError, KeyError, TypeError) as e:
401
+ self.logger.warning(
402
+ f"Failed to load component {card.hash}: {str(e)}"
403
+ )
404
+ continue
405
+
406
+ self.logger.info(
407
+ f"Found {len(components)} compatible components for {dimension}"
408
+ )
409
+
410
+ return components
411
+
412
+ except (ValueError, TypeError, KeyError, AttributeError) as e:
413
+ self.logger.error(
414
+ f"Failed to find compatible components: {str(e)}", exc_info=True
415
+ )
416
+ return []
417
+
418
+ def _validate_clm_assembly(
419
+ self, abstract: CLMComponent, concrete: CLMComponent, balanced: CLMComponent
420
+ ) -> ValidationResult:
421
+ """Validate the consistency of assembled CLM components."""
422
+ errors = []
423
+ warnings = []
424
+ consistency_checks = {
425
+ "input_consistency": True,
426
+ "output_coverage": True,
427
+ "operation_testing": True,
428
+ "semantic_consistency": True,
429
+ }
430
+
431
+ try:
432
+ is_valid = True
433
+ self.logger.info("CLM assembly validation: VALID (lenient mode)")
434
+
435
+ return ValidationResult(
436
+ is_valid=is_valid,
437
+ errors=errors,
438
+ warnings=warnings,
439
+ consistency_checks=consistency_checks,
440
+ )
441
+
442
+ except (ValueError, TypeError, KeyError) as e:
443
+ self.logger.error(f"CLM assembly validation error: {str(e)}", exc_info=True)
444
+ return ValidationResult(
445
+ is_valid=False,
446
+ errors=[f"Validation error: {str(e)}"],
447
+ warnings=[],
448
+ consistency_checks={},
449
+ )
450
+
451
+ def list_assembled_clms(self) -> list[AssembledCLM]:
452
+ """List all assembled CLMs in the collection."""
453
+ try:
454
+ found_cards = self.collection.search_by_string("Assembled_CLM")
455
+ assembled_clms = []
456
+
457
+ for card in found_cards.items:
458
+ try:
459
+ assembled_clm = self.load_assembled_clm(card.hash)
460
+ assembled_clms.append(assembled_clm)
461
+ except (ValueError, KeyError, TypeError) as e:
462
+ self.logger.warning(
463
+ f"Failed to load assembled CLM {card.hash}: {str(e)}"
464
+ )
465
+ continue
466
+
467
+ self.logger.info(f"Found {len(assembled_clms)} assembled CLMs")
468
+
469
+ return assembled_clms
470
+
471
+ except (ValueError, TypeError, KeyError, AttributeError) as e:
472
+ self.logger.error(f"Failed to list assembled CLMs: {str(e)}", exc_info=True)
473
+ return []
474
+
475
+
476
+ __all__ = [
477
+ "AssembledCLM",
478
+ "CLMAssembler",
479
+ "CLMComponent",
480
+ "ValidationResult",
481
+ ]
@@ -0,0 +1,23 @@
1
+ """Pure CEL Expression Models and AST Schemas in Layer 0 (Sprint 384 / DEL-384-04).
2
+
3
+ Stateless Kenotic core representation for Common Expression Language ASTs,
4
+ predicates, field assertions, and RLCD meet contracts.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from clm.layer0.cel_eval import (
10
+ BailVerdict,
11
+ CelEvaluationResult,
12
+ CelEvaluator,
13
+ evaluate_cel_condition,
14
+ evaluate_vcard_meet,
15
+ )
16
+
17
+ __all__ = [
18
+ "BailVerdict",
19
+ "CelEvaluationResult",
20
+ "CelEvaluator",
21
+ "evaluate_cel_condition",
22
+ "evaluate_vcard_meet",
23
+ ]