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,262 @@
1
+ """Layer 0 Verifier Core — Precondition validation and Execution MCard emission.
2
+
3
+ Extracted from clm.layer1.verifier to resolve Girard paradox violation V-1:
4
+ algebra_baldwin.py (Layer 0) was importing emit_exec_mcard_py and
5
+ verify_precondition from verifier.py (Layer 1), creating an upward
6
+ dependency that breaks the Type Lattice SSOT principle (type_lattice.md §4.5).
7
+
8
+ These functions depend only on Layer 0 primitives:
9
+ - clm.layer0.db (CLMDB, CLMRepository, resolve_clm_path)
10
+ - clm.layer0.utils (clm_hash_file, clm_hash_string, detect_host_os)
11
+ - clm.layer0.algebra (load_normalized_manifest_str — lazy)
12
+ - clm.layer0.type_registry (TypeRegistry — lazy)
13
+ - clm.cross_cutting.clm_logger (get_logger)
14
+ """
15
+
16
+ import os
17
+ import sys
18
+ import time
19
+
20
+ import yaml
21
+
22
+ from clm.cross_cutting.clm_logger import get_logger
23
+ from clm.layer0.utils import (
24
+ clm_hash_file,
25
+ clm_hash_string,
26
+ detect_host_os,
27
+ resolve_clm_path,
28
+ )
29
+
30
+
31
+ def _get_storage():
32
+ target = "clm.layer2.storage"
33
+ mod = sys.modules.get(target)
34
+ if mod is None:
35
+ __import__(target)
36
+ mod = sys.modules.get(target)
37
+ return mod
38
+
39
+ _logger = get_logger("clm.layer0.verifier_core")
40
+
41
+
42
+ def _get_load_manifest_str():
43
+ from clm.layer0.algebra import load_normalized_manifest_str
44
+ return load_normalized_manifest_str
45
+
46
+
47
+ def verify_precondition(clm_root: str, clm_file: str) -> bool:
48
+ """
49
+ Validates the precondition bounds and zero-trust identity before executing a PCard.
50
+
51
+ Args:
52
+ clm_root (str): The root directory of the CLM workspace.
53
+ clm_file (str): The path to the CLM PCard file.
54
+
55
+ Returns:
56
+ bool: True if authorized and validated, False otherwise.
57
+ """
58
+ load_normalized_manifest_str_fn = _get_load_manifest_str()
59
+ clm_file = resolve_clm_path(clm_root, clm_file)
60
+ stub = os.path.join(clm_root, "kernel", "scripts", "clmEval")
61
+ eval_yaml = os.path.join(clm_root, "computable_knowledge/Abstract/layer5_system/bootstrap/evaluator/clmEval.yaml")
62
+ if os.path.exists(stub) and os.path.exists(eval_yaml):
63
+ stub_cert = ""
64
+ with open(stub, encoding="utf-8") as f:
65
+ for line in f:
66
+ if "_EXPECTED_HASH=" in line:
67
+ parts = line.split('="')
68
+ if len(parts) > 1:
69
+ stub_cert = parts[1].split('"')[0]
70
+ break
71
+ yaml_hash = clm_hash_file(eval_yaml)
72
+ if stub_cert and stub_cert != yaml_hash:
73
+ import hashlib
74
+ with open(eval_yaml, "rb") as yf:
75
+ norm_yaml = yf.read().replace(b"\r\n", b"\n").replace(b"\r", b"\n")
76
+ if stub_cert != hashlib.sha256(norm_yaml).hexdigest():
77
+ _logger.error("[VERIFY] ❌ Integrity failure: stub certificate mismatch")
78
+ _logger.info(f"[VERIFY] Stub expects: {stub_cert}")
79
+ _logger.info(f"[VERIFY] YAML actual: {yaml_hash}")
80
+ return False
81
+ _logger.info("[VERIFY] ✅ Bidirectional integrity verified")
82
+ _logger.info(f"[VERIFY] YAML hash: {yaml_hash}")
83
+ _logger.info(f"[VERIFY] Stub hash: {clm_hash_file(stub)}")
84
+
85
+ host_os = detect_host_os()
86
+
87
+ root_did = f"did:pkc:ca:{host_os}:root-agent"
88
+ storage = _get_storage()
89
+ db = storage.CLMDB(clm_root) if storage else None
90
+ repo = storage.CLMRepository(db, clm_root) if storage and db else None
91
+
92
+ if not repo.has_card(root_did, "agent_identities"):
93
+ _logger.info(f"[VERIFY] Bootstrapping root CA agent: {root_did}")
94
+ g_time = time.strftime("%Y-%m-%dT%H:%M:%S%z")
95
+ yaml_content = f"""agent:
96
+ did: "{root_did}"
97
+ type: "CA"
98
+ metadata:
99
+ os: "{host_os}"
100
+ name: "Root CA Agent"
101
+ capabilities:
102
+ - "admin"
103
+ - "exec"
104
+ """
105
+ repo.save_card_and_handle("agent:root", root_did, yaml_content, "agent_identities", timestamp=g_time, replace=False)
106
+
107
+ virtual_dids = ["did:clm:evaluator", "did:clm:cache_manager", "did:clm:iam_agent", "did:clm:ci_pipeline"]
108
+ for v_did in virtual_dids:
109
+ if not repo.has_card(v_did, "agent_identities"):
110
+ g_time = time.strftime("%Y-%m-%dT%H:%M:%S%z")
111
+ yaml_content = f"""agent:
112
+ did: "{v_did}"
113
+ type: "CA"
114
+ metadata:
115
+ name: "Virtual {v_did} Agent"
116
+ capabilities:
117
+ - "admin"
118
+ - "exec"
119
+ """
120
+ repo.save_card(v_did, yaml_content, "agent_identities", timestamp=g_time, replace=False)
121
+
122
+ if "ACTIVE_AGENT_DID" not in os.environ:
123
+ os.environ["ACTIVE_AGENT_DID"] = root_did
124
+
125
+ active_did = os.environ["ACTIVE_AGENT_DID"]
126
+ _logger.info(f"[VERIFY] Active Agent DID: {active_did}")
127
+
128
+ agent_card_res = repo.get_card_content(active_did, "agent_identities")
129
+ if not agent_card_res or not agent_card_res.strip():
130
+ _logger.error(f"[VERIFY] ❌ Unauthorized agent: {active_did} is not registered.")
131
+ return False
132
+
133
+ try:
134
+ agent_data = yaml.safe_load(agent_card_res.strip())
135
+ caps = agent_data.get("agent", {}).get("capabilities", [])
136
+ if not any(c in caps for c in ["exec", "admin"]):
137
+ _logger.error(f"[VERIFY] ❌ Agent {active_did} lacks required 'exec' or 'admin' capability.")
138
+ return False
139
+ except Exception as e:
140
+ _logger.error(f"[VERIFY] ❌ Failed to parse agent capabilities: {e}")
141
+ return False
142
+
143
+ _logger.info("[VERIFY] ✅ Agent authorized successfully")
144
+
145
+ strict_types = os.environ.get("CLM_STRICT_TYPES", "").lower() == "true"
146
+ if clm_file and os.path.exists(clm_file):
147
+ content_str = load_normalized_manifest_str_fn(clm_root, clm_file)
148
+ type_name = "mcard"
149
+ extract_key = None
150
+ if "_meta:" in content_str:
151
+ type_name = "clm_manifest"
152
+ extract_key = "_meta"
153
+ elif "vpre:" in content_str or "vpost:" in content_str or "vcard_token:" in content_str:
154
+ type_name = "vcard_token"
155
+ extract_key = "vcard_token"
156
+ elif "abstract_spec:" in content_str:
157
+ type_name = "a_mcard"
158
+ extract_key = "abstract_spec"
159
+
160
+ payload_content = content_str
161
+ try:
162
+ parsed = yaml.safe_load(content_str)
163
+ inner = parsed.get("clm", parsed)
164
+ if extract_key and isinstance(inner, dict) and extract_key in inner:
165
+ payload_content = yaml.dump(inner[extract_key])
166
+ except Exception:
167
+ pass
168
+
169
+ try:
170
+ from clm.layer0.type_registry import TypeRegistry
171
+ registry = TypeRegistry(clm_root)
172
+ if type_name == "mcard" and not registry.get_type_info("mcard"):
173
+ _logger.warning("[VERIFY] ⚠️ Skipping type validation: 'mcard' is not registered.")
174
+ else:
175
+ registry.validate(type_name, payload_content)
176
+ _logger.info(f"[VERIFY] ✅ Type validation passed (type: {type_name})")
177
+ except Exception as e:
178
+ if strict_types:
179
+ _logger.error(f"[VERIFY] ❌ TYPE_ERROR: Type validation failed for '{clm_file}'!")
180
+ _logger.error(f"Error: {e}")
181
+ return False
182
+ else:
183
+ _logger.warning(f"[VERIFY] ⚠️ TYPE_WARNING: Type validation failed for '{clm_file}' (Strict mode is OFF)")
184
+ _logger.info(f"Details: {e}")
185
+ return True
186
+
187
+
188
+ def emit_exec_mcard_py(
189
+ clm_root: str,
190
+ operation: str,
191
+ content_hash: str,
192
+ extra_yaml: str = "",
193
+ a_hash: str = "",
194
+ c_hash: str = "",
195
+ ) -> str:
196
+ """
197
+ Emits an Execution MCard to the Tri-Database to track state changes.
198
+
199
+ Args:
200
+ clm_root (str): The root directory of the CLM workspace.
201
+ operation (str): The operation being performed.
202
+ content_hash (str): The hash of the content involved.
203
+ extra_yaml (str): Additional YAML content to append.
204
+ a_hash (str): The Abstract Specification hash.
205
+ c_hash (str): The Concrete Implementation hash.
206
+
207
+ Returns:
208
+ str: The path to the emitted MCard file.
209
+ """
210
+ storage = _get_storage()
211
+ db = storage.CLMDB(clm_root) if storage else None
212
+ zero_fs = db.zero_fs if db else (os.environ.get("CLM_ZERO_FS", "").lower() in ("true", "1"))
213
+ mcard_dir = os.path.join(clm_root, "data/execution_logs")
214
+ if zero_fs:
215
+ mcard_dir = os.path.join(os.environ.get("TMPDIR", "/tmp"), "data/execution_logs")
216
+ os.makedirs(mcard_dir, exist_ok=True)
217
+
218
+ g_time = time.strftime("%Y-%m-%dT%H:%M:%S%z")
219
+ unix_ts = int(time.time())
220
+ mcard_file = os.path.join(mcard_dir, f"exec_{unix_ts}_{content_hash[:8]}.yaml")
221
+
222
+ lines = []
223
+ lines.append("mcard:")
224
+ lines.append(f' g_time: "{g_time}"')
225
+ lines.append(f' content_hash: "{content_hash}"')
226
+ lines.append(f' operation: "{operation}"')
227
+ lines.append(f' agent_did: "{os.environ.get("ACTIVE_AGENT_DID", "")}"')
228
+
229
+ if extra_yaml:
230
+ for line in extra_yaml.strip().splitlines():
231
+ lines.append(f" {line}")
232
+
233
+ if a_hash or c_hash:
234
+ lines.append(" source:")
235
+ if a_hash:
236
+ lines.append(f' a_hash: "{a_hash}"')
237
+ if c_hash:
238
+ lines.append(f' c_hash: "{c_hash}"')
239
+ lines.append(f' operation: "{operation}"')
240
+ facts = os.environ.get("CLM_RUNTIME_FACTS")
241
+ if facts:
242
+ lines.append(" runtime_facts:")
243
+ for line in facts.strip().splitlines():
244
+ lines.append(f" {line}")
245
+ else:
246
+ facts = os.environ.get("CLM_RUNTIME_FACTS")
247
+ if facts:
248
+ lines.append(" runtime_facts:")
249
+ for line in facts.strip().splitlines():
250
+ lines.append(f" {line}")
251
+
252
+ mcard_content = "\n".join(lines) + "\n"
253
+
254
+ if not zero_fs:
255
+ with open(mcard_file, "w", encoding="utf-8") as f:
256
+ f.write(mcard_content)
257
+
258
+ mcard_hash = clm_hash_string(mcard_content)
259
+ if storage and db:
260
+ repo = storage.CLMRepository(db, clm_root)
261
+ repo.save_card(mcard_hash, mcard_content, "execution_log", timestamp=g_time, replace=False)
262
+ return mcard_file
clm/layer1/__init__.py ADDED
@@ -0,0 +1,31 @@
1
+ """CLM layer1 layer package."""
2
+
3
+ from clm.layer1.gate_composer import compose_conditions_cmd, run_nested_evaluate
4
+ from clm.layer1.matrix import IncidenceMatrix, math_gcd, math_lcm, solve_nullspace
5
+ from clm.layer1.petri import ColoredPetriVM, petri_run_net
6
+ from clm.layer1.runtime_adapter import (
7
+ evaluate_compose,
8
+ evaluate_polyglot,
9
+ run_internal_reference_test,
10
+ )
11
+ from clm.layer1.test_runner import run_algebra_op, test_baldwin_operators
12
+ from clm.layer1.verifier import (
13
+ check_precondition_py,
14
+ emit_exec_mcard_py,
15
+ get_load_manifest,
16
+ get_load_manifest_str,
17
+ normalize_output_py,
18
+ resolve_active_hashes_py,
19
+ validate_postcondition,
20
+ verify_precondition,
21
+ )
22
+ from clm.layer1.vm import PetriVM
23
+
24
+ __all__ = [
25
+ 'petri_run_net', 'ColoredPetriVM', 'PetriVM', 'IncidenceMatrix', 'solve_nullspace', 'math_gcd', 'math_lcm',
26
+ 'compose_conditions_cmd', 'run_nested_evaluate', 'run_internal_reference_test', 'evaluate_polyglot',
27
+ 'evaluate_compose', 'get_load_manifest_str', 'get_load_manifest', 'verify_precondition',
28
+ 'validate_postcondition', 'emit_exec_mcard_py', 'resolve_active_hashes_py', 'check_precondition_py',
29
+ 'normalize_output_py', 'run_algebra_op', 'test_baldwin_operators'
30
+ ]
31
+
@@ -0,0 +1,275 @@
1
+ """Action Execution Dispatcher (Sprint 393 / DEL-393-01).
2
+
3
+ Bridges declarative Action manifests (clm.action.v1) to the Layer 1 algebraic execution core.
4
+ Resolves content-addressed MCards, dispatches to domain-aware Baldwin manipulators,
5
+ enforces the Zero Mutation Invariant on inputs, and registers output MCards in CAS.
6
+
7
+ Acceptance Criteria:
8
+ - AC-393-01-01: ActionDispatcher.execute() resolves inputs from CAS and returns typed ExecutionResult.
9
+ - AC-393-01-02: Zero Mutation Invariant on input MCards (input hash unchanged post-execution).
10
+ - AC-393-01-03: Unresolved input URIs raise InputResolutionError prior to operator execution.
11
+ - AC-393-01-04: Execution metrics (wall time, bytes processed) recorded in ExecutionResult.
12
+
13
+ Layer 1 module (no imports above L1).
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import time
19
+ from dataclasses import dataclass, field
20
+ from pathlib import Path
21
+ from typing import Any
22
+
23
+ from clm.cross_cutting.domain_models import MCard
24
+ from clm.layer0.exceptions import CLMError
25
+ from clm.layer0.model.action import ActionManifest
26
+ from clm.layer0.model.card_triad import compute_canonical_hash
27
+ from clm.layer0.utils import clm_hash_string
28
+ from clm.layer1.operations.manipulators import (
29
+ DocumentManipulator,
30
+ MediaManipulator,
31
+ StructuredManipulator,
32
+ TabularManipulator,
33
+ )
34
+
35
+
36
+ class InputResolutionError(CLMError):
37
+ """Raised when an action input cannot be resolved from bindings or CAS."""
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class ExecutionResult:
42
+ """Certified outcome of an Action execution."""
43
+
44
+ status: str
45
+ operator: str
46
+ outputs: dict[str, MCard] = field(default_factory=dict)
47
+ input_hashes: dict[str, str] = field(default_factory=dict)
48
+ output_hashes: dict[str, str] = field(default_factory=dict)
49
+ metrics: dict[str, Any] = field(default_factory=dict)
50
+ error: str | None = None
51
+
52
+ @property
53
+ def is_success(self) -> bool:
54
+ return self.status == "success"
55
+
56
+
57
+ class ActionDispatcher:
58
+ """Dispatches declarative Action manifests to Baldwin modality manipulators."""
59
+
60
+ @classmethod
61
+ def execute(
62
+ cls,
63
+ manifest: ActionManifest | str | Path | dict[str, Any],
64
+ input_bindings: dict[str, Any] | None = None,
65
+ fs: Any = None,
66
+ ) -> ExecutionResult:
67
+ """Execute an Action manifest against content-addressed MCards."""
68
+ t_start = time.perf_counter()
69
+ bindings = dict(input_bindings or {})
70
+
71
+ # 1. Parse manifest if string, Path, or dict
72
+ if isinstance(manifest, (str, Path)):
73
+ action = ActionManifest.from_yaml(manifest)
74
+ elif isinstance(manifest, dict):
75
+ action = ActionManifest.from_dict(manifest)
76
+ elif isinstance(manifest, ActionManifest):
77
+ action = manifest
78
+ else:
79
+ raise TypeError(f"Invalid manifest type: {type(manifest)}")
80
+
81
+ operator = action.operation.operator
82
+ params = action.operation.parameters or {}
83
+
84
+ # 2. Resolve inputs and check AC-393-01-03 (InputResolutionError)
85
+ resolved_inputs: dict[str, MCard] = {}
86
+ input_hashes_before: dict[str, str] = {}
87
+ original_card_hashes: dict[str, str] = {}
88
+ bytes_processed = 0
89
+
90
+ for inp in action.inputs:
91
+ card: MCard | None = None
92
+ # Check direct binding by input name or URI
93
+ if inp.name in bindings:
94
+ bound = bindings[inp.name]
95
+ if isinstance(bound, MCard):
96
+ card = bound
97
+ else:
98
+ # Raw payload provided, wrap in transient MCard
99
+ digest = clm_hash_string(bound) if isinstance(bound, str) else compute_canonical_hash(bound)
100
+ card = MCard.create(
101
+ uri=f"mcard:{digest[:16]}",
102
+ payload=bound,
103
+ author="did:clm:user",
104
+ )
105
+ elif inp.uri and inp.uri in bindings:
106
+ bound = bindings[inp.uri]
107
+ if isinstance(bound, MCard):
108
+ card = bound
109
+ else:
110
+ digest = clm_hash_string(bound) if isinstance(bound, str) else compute_canonical_hash(bound)
111
+ card = MCard.create(
112
+ uri=inp.uri,
113
+ payload=bound,
114
+ author="did:clm:user",
115
+ )
116
+ elif inp.uri and fs is not None:
117
+ # Attempt resolution from CAS filesystem
118
+ try:
119
+ clean_uri = inp.uri
120
+ if clean_uri.startswith("mcard://"):
121
+ clean_uri = "mcard:" + clean_uri[len("mcard://"):]
122
+ card = fs.read_file(clean_uri)
123
+ except Exception:
124
+ card = None
125
+
126
+ if card is None and inp.required:
127
+ raise InputResolutionError(
128
+ f"Required input '{inp.name}' (uri={inp.uri}) could not be resolved"
129
+ )
130
+
131
+ if card is not None:
132
+ resolved_inputs[inp.name] = card
133
+ original_card_hashes[inp.name] = str(card.hash)
134
+ if isinstance(card.payload, str):
135
+ h_str = clm_hash_string(card.payload)
136
+ elif isinstance(card.payload, bytes):
137
+ from clm.layer0.utils import clm_hash_bytes
138
+ h_str = clm_hash_bytes(card.payload)
139
+ else:
140
+ h_str = str(card.hash)
141
+ input_hashes_before[inp.name] = h_str
142
+ # Count bytes
143
+ if isinstance(card.payload, (str, bytes)):
144
+ bytes_processed += len(card.payload)
145
+ elif card.content:
146
+ bytes_processed += len(card.content)
147
+
148
+ # 3. Select Modality Manipulator
149
+ primary_input = next(iter(resolved_inputs.values())) if resolved_inputs else None
150
+ primary_format = action.inputs[0].format if action.inputs else None
151
+
152
+ if primary_format is None and primary_input and hasattr(primary_input, "metadata"):
153
+ primary_format = primary_input.metadata.get("format")
154
+
155
+ manipulator = cls._select_manipulator(primary_format, primary_input)
156
+
157
+ # 4. Invoke Algebraic Operator
158
+ try:
159
+ payload = primary_input.payload if primary_input else None
160
+ op_method = getattr(manipulator, operator, None)
161
+ if not op_method:
162
+ raise ValueError(f"Manipulator {manipulator.__name__} does not support operator '{operator}'")
163
+
164
+ op_out = op_method(payload, params)
165
+
166
+ # 5. AC-393-01-02: Enforce Zero Mutation Invariant on inputs
167
+ for name, card in resolved_inputs.items():
168
+ expected_hash = original_card_hashes[name]
169
+ current_hash = str(card.hash)
170
+ if current_hash != expected_hash:
171
+ raise AssertionError(
172
+ f"Zero Mutation Invariant violated for input '{name}': hash mutated from {expected_hash} to {current_hash}"
173
+ )
174
+
175
+ # 6. Map operator output to ActionOutputs
176
+ outputs: dict[str, MCard] = {}
177
+ output_hashes: dict[str, str] = {}
178
+
179
+ if isinstance(op_out, dict) and len(action.outputs) > 1:
180
+ # Multi-output split
181
+ for out_spec in action.outputs:
182
+ out_name = out_spec.name
183
+ part_payload = op_out.get(out_name)
184
+ if part_payload is None:
185
+ # Fallback to key index
186
+ part_payload = next(iter(op_out.values()), "")
187
+
188
+ digest = clm_hash_string(part_payload) if isinstance(part_payload, str) else compute_canonical_hash(part_payload)
189
+ handle = out_spec.handle or f"mcard:{out_name}"
190
+ clean_uri = handle if handle.startswith("mcard:") else f"mcard:{handle}"
191
+ out_card = MCard.create(
192
+ uri=clean_uri,
193
+ payload=part_payload,
194
+ author=action.clm.author,
195
+ metadata={"format": out_spec.format or primary_format, "generator": action.clm.name},
196
+ )
197
+ outputs[out_name] = out_card
198
+ output_hashes[out_name] = digest
199
+ if fs is not None:
200
+ fs.write_file(uri=clean_uri, payload=part_payload, author=action.clm.author, metadata=out_card.metadata)
201
+
202
+ else:
203
+ # Single output or undivided result
204
+ out_spec = action.outputs[0]
205
+ out_name = out_spec.name
206
+ part_payload = op_out.get(out_name, op_out) if isinstance(op_out, dict) else op_out
207
+
208
+ digest = clm_hash_string(part_payload) if isinstance(part_payload, str) else compute_canonical_hash(part_payload)
209
+ handle = out_spec.handle or f"mcard:{out_name}"
210
+ clean_uri = handle if handle.startswith("mcard:") else f"mcard:{handle}"
211
+ out_card = MCard.create(
212
+ uri=clean_uri,
213
+ payload=part_payload,
214
+ author=action.clm.author,
215
+ metadata={"format": out_spec.format or primary_format, "generator": action.clm.name},
216
+ )
217
+ outputs[out_name] = out_card
218
+ output_hashes[out_name] = digest
219
+ if fs is not None:
220
+ fs.write_file(uri=clean_uri, payload=part_payload, author=action.clm.author, metadata=out_card.metadata)
221
+
222
+ t_elapsed = (time.perf_counter() - t_start) * 1000.0
223
+
224
+ return ExecutionResult(
225
+ status="success",
226
+ operator=operator,
227
+ outputs=outputs,
228
+ input_hashes=input_hashes_before,
229
+ output_hashes=output_hashes,
230
+ metrics={
231
+ "wall_time_ms": round(t_elapsed, 3),
232
+ "bytes_processed": bytes_processed,
233
+ "operator": operator,
234
+ "action_name": action.clm.name,
235
+ },
236
+ )
237
+
238
+ except Exception as e:
239
+ t_elapsed = (time.perf_counter() - t_start) * 1000.0
240
+ return ExecutionResult(
241
+ status="failed",
242
+ operator=operator,
243
+ input_hashes=input_hashes_before,
244
+ metrics={"wall_time_ms": round(t_elapsed, 3), "bytes_processed": bytes_processed},
245
+ error=str(e),
246
+ )
247
+
248
+ @staticmethod
249
+ def _select_manipulator(fmt: str | None, primary_input: MCard | None) -> type:
250
+ """Select appropriate modality manipulator."""
251
+ if fmt in ("csv", "tsv", "tabular"):
252
+ return TabularManipulator
253
+ if fmt in ("markdown", "text", "txt", "md"):
254
+ return DocumentManipulator
255
+ if fmt in ("json", "yaml", "yml"):
256
+ return StructuredManipulator
257
+ if fmt in ("image", "audio", "media", "binary", "model3d"):
258
+ return MediaManipulator
259
+
260
+ # Infer from payload
261
+ if primary_input and primary_input.payload is not None:
262
+ p = primary_input.payload
263
+ if isinstance(p, (dict, list)):
264
+ return StructuredManipulator
265
+ if isinstance(p, bytes):
266
+ return MediaManipulator
267
+ if isinstance(p, str):
268
+ if "\n" in p and ("," in p.splitlines()[0] or "\t" in p.splitlines()[0]):
269
+ return TabularManipulator
270
+ if p.startswith("#") or "##" in p:
271
+ return DocumentManipulator
272
+ if p.strip().startswith("{") or p.strip().startswith("["):
273
+ return StructuredManipulator
274
+
275
+ return TabularManipulator