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,434 @@
1
+ """Cross-Cutting — PCard (Π-type / Control Plane / Lens)
2
+
3
+ PCard is the computation type / Dependent Product (Π-type) of the MVP Cards triad.
4
+ It encodes transformations as polynomial functors over MCard references.
5
+ PCard functions as the Monadic Executor: handling dynamic control flow and
6
+ dependent sequencing via Reader, State, and Writer monadic patterns.
7
+
8
+ Design references:
9
+ - MVP Cards Design Rationale (§PCard — Control Plane)
10
+ - Function-Number Duality
11
+ - The Currying Adjunction
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import hashlib
17
+ import os
18
+ import sys
19
+ import time
20
+ from collections.abc import Callable
21
+ from typing import Any
22
+
23
+ from clm.cross_cutting.cel_engine import ( # noqa: F401
24
+ _DEP_LOGGER,
25
+ _DEPRECATED_FUNCS,
26
+ _evaluate_cel,
27
+ _evaluate_expr,
28
+ _resolve_arg,
29
+ _smart_evaluate,
30
+ )
31
+ from clm.cross_cutting.clm_logger import get_logger
32
+ from clm.cross_cutting.telemetry import jsonl_emit_typed
33
+ from clm.cross_cutting.timeutil import default_agent_did
34
+ from clm.layer0.context import CLMContext
35
+ from clm.layer0.utils import clm_hash_string as hash_string
36
+
37
+ _logger = get_logger("clm.pcard")
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # Sprint 384 (DEL-384-02): Re-export canonical PCard from Layer 0 card_triad
41
+ from clm.layer0.model.card_triad import PCard # noqa: F401
42
+
43
+ # Dependency Inversion hooks for Layer 2 classifier integration
44
+ _classifier_hook: tuple[Callable, Callable] | None = None
45
+ _classifier_hook_resolver: Callable[[], tuple[Callable, Callable] | None] | None = None
46
+
47
+
48
+ def register_classifier_hook(classify_fn: Callable, dialect_fn: Callable) -> None:
49
+ """Register classifier and dialect detection functions (Dependency Inversion)."""
50
+ global _classifier_hook
51
+ _classifier_hook = (classify_fn, dialect_fn)
52
+
53
+
54
+ def register_classifier_hook_resolver(resolver: Callable[[], tuple[Callable, Callable] | None]) -> None:
55
+ """Register lazy resolver for classifier hook."""
56
+ global _classifier_hook_resolver
57
+ _classifier_hook_resolver = resolver
58
+
59
+
60
+ # ---------------------------------------------------------------------------
61
+ # PCard Serialization
62
+ # ---------------------------------------------------------------------------
63
+
64
+ def serialize_pcard(
65
+ ctx: CLMContext,
66
+ operation: str,
67
+ runtime: str,
68
+ script_hash: str,
69
+ input_place_hashes: list[str],
70
+ timestamp: str,
71
+ ) -> str:
72
+ """Serialize a PCard token and persist it to the execution log.
73
+
74
+ A PCard (Π-type / Dependent Product) encodes a transformation as a
75
+ polynomial functor over MCard references. This function freezes the
76
+ live PCard into an MCard (Function-Number Duality: a verb stored as
77
+ a noun / gerund) and commits it to the execution_log pillar.
78
+
79
+ Sprint 131.5: YAML emission now delegates to ``Card(token_type="pcard", ...).to_yaml()``
80
+ so the unified model is the single source of truth; the ``save_card_and_handle``
81
+ and ``jsonl_emit`` side effects are preserved.
82
+ """
83
+ from clm.cross_cutting.mcard import Card
84
+
85
+ pcard_yaml = Card(
86
+ token_type="pcard",
87
+ operation=operation,
88
+ runtime=runtime,
89
+ script_hash=script_hash,
90
+ timestamp=timestamp,
91
+ input_place_hashes=input_place_hashes,
92
+ ).to_yaml()
93
+
94
+ pcard_hash = hash_string(pcard_yaml)
95
+
96
+ handle_name = f"pcard:{operation}:{pcard_hash}"
97
+ ctx.repo.save_card_and_handle(
98
+ handle_name, pcard_hash, pcard_yaml, "execution_log",
99
+ timestamp=timestamp, replace=False,
100
+ )
101
+
102
+ jsonl_emit_typed("pcard_serialized", {
103
+ "pcard_hash": pcard_hash,
104
+ "operation": operation,
105
+ "runtime": runtime,
106
+ "script_hash": script_hash,
107
+ "input_place_hashes": input_place_hashes,
108
+ }, ctx.root)
109
+ return pcard_hash
110
+
111
+
112
+ # ---------------------------------------------------------------------------
113
+ # Operation Registry
114
+ # ---------------------------------------------------------------------------
115
+
116
+ _TRIDB_OP_NAMES = [
117
+ "verify_tables", "evaluator_functions", "mcard_kernel", "memorize_mcard",
118
+ "polyglot_ingest", "modular_adapters", "polyglot_execution", "polyglot_parity",
119
+ "polyglot_generalization", "normalize_syntax", "validate_type_lattice",
120
+ "type_system", "exclude", "assert_algebraic_operators", "check_precondition",
121
+ "execute_composed_pcard", "verify_authorization", "validate_session_lifecycle",
122
+ "verify_zero_fs_isolation", "dispatch_over_loopback",
123
+ ]
124
+
125
+
126
+ class OperationRegistry:
127
+ """Maps operation names to callable implementations.
128
+
129
+ The default registry bootstraps the Tri-Database for all Stage 1
130
+ operations. Additional operations can be registered at runtime.
131
+ """
132
+
133
+ def __init__(self) -> None:
134
+ import sys
135
+ target = "clm.layer2.storage"
136
+ mod = sys.modules.get(target)
137
+ if mod is None:
138
+ __import__(target)
139
+ mod = sys.modules.get(target)
140
+ init_tridb = mod.init_tridb
141
+ # Sprint 132.3: replaced 20 identical lambdas with functools.partial
142
+ # Sprint 132.5: lazy-init TriDB once per tmp_dir (was 20x init_tridb)
143
+ self._init_tridb = init_tridb
144
+ self._tridb_initialised: set[str] = set()
145
+ self._ops: dict[str, Callable] = dict.fromkeys(_TRIDB_OP_NAMES, self._lazy_tridb)
146
+
147
+ def _lazy_tridb(self, tmp_dir: str, **kw: Any) -> int:
148
+ """Lazy-init TriDB once per tmp_dir, then no-op (Sprint 132.5)."""
149
+ if tmp_dir not in self._tridb_initialised:
150
+ self._init_tridb(tmp_dir)
151
+ self._tridb_initialised.add(tmp_dir)
152
+ return 0
153
+
154
+ def register(self, name: str, fn: Callable) -> None:
155
+ """Register an operation handler: ``fn(tmp_dir, **kw) -> int``."""
156
+ self._ops[name] = fn
157
+
158
+ def dispatch(self, operation: str, tmp_dir: str, **kwargs: Any) -> int:
159
+ """Dispatch *operation* and return its exit code."""
160
+ fn = self._ops.get(operation)
161
+ if fn is None:
162
+ raise ValueError(f"Unknown operation: {operation}")
163
+ return fn(tmp_dir, **kwargs)
164
+
165
+
166
+ # ---------------------------------------------------------------------------
167
+ # Post-context builder — DELETED in Sprint 128.5
168
+ # Replaced by clm.cross_cutting.cel_store.build_store() which returns a
169
+ # CelStore (typed, Flux-pattern) whose .to_dict() produces the same context
170
+ # dict shape that op handlers expect.
171
+ # ---------------------------------------------------------------------------
172
+
173
+
174
+ # ---------------------------------------------------------------------------
175
+ # Sprint 130.2 — Runtime-agnostic verify_test_file expansion
176
+ # ---------------------------------------------------------------------------
177
+
178
+ _TEST_RUNTIMES = {
179
+ ".py": ("python", lambda clm_root: {
180
+ "CLM_ROOT": {"ref": "env.clm_root"},
181
+ "PYTHONPATH": {"op": "path_join", "parts": [{"ref": "env.clm_root"}, "kernel/scripts"]},
182
+ }),
183
+ ".sh": ("shell", lambda clm_root: {
184
+ "CLM_ROOT": {"ref": "env.clm_root"},
185
+ }),
186
+ ".rs": ("rust", lambda clm_root: {
187
+ "CLM_ROOT": {"ref": "env.clm_root"},
188
+ "CARGO_TARGET_DIR": {"op": "path_join", "parts": [{"ref": "env.clm_root"}, "target"]},
189
+ }),
190
+ }
191
+
192
+
193
+ def _expand_verify_test_file(verify_file: str, operation: str) -> dict:
194
+ """Expand a ``verify_test_file`` shorthand into vcard_pre + vcard_post blocks.
195
+
196
+ Auto-detects the test file extension (.py, .sh, .rs) and builds
197
+ runtime-appropriate env vars. Returns a dict with ``vcard_pre`` and
198
+ ``vcard_post`` keys.
199
+ """
200
+ import os
201
+
202
+ ext = os.path.splitext(verify_file)[1]
203
+ runtime_info = _TEST_RUNTIMES.get(ext, _TEST_RUNTIMES[".py"])
204
+ label, env_builder = runtime_info
205
+
206
+ return {
207
+ "vcard_pre": [{
208
+ "test_case": f"{operation} {label} suite exists",
209
+ "gate": "gate:file_exists",
210
+ "value": {
211
+ "op": "path_join",
212
+ "parts": [{"ref": "env.clm_root"}, verify_file],
213
+ },
214
+ }],
215
+ "vcard_post": [{
216
+ "test_case": f"{operation} {label} suite passes",
217
+ "gate": "gate:hash_matches",
218
+ "expected": 0,
219
+ "actual": {
220
+ "op": "run_test_suite",
221
+ "test_file": verify_file,
222
+ "env": env_builder({"ref": "env.clm_root"}),
223
+ },
224
+ }],
225
+ }
226
+
227
+
228
+ # ---------------------------------------------------------------------------
229
+ # Balanced Runner (Orchestrator)
230
+ # ---------------------------------------------------------------------------
231
+
232
+ class BalancedRunner:
233
+ """Orchestrates Face B (Balanced Expectations) verification.
234
+
235
+ For each ``pending_case`` in the manifest:
236
+
237
+ 1. Evaluates ``vcard_pre`` gates (precondition checks).
238
+ 2. Creates a sandboxed environment (``CLMTestSandbox``).
239
+ 3. Wraps execution in a ``VCardSandwich`` (Gatekeeper Pattern).
240
+ 4. Dispatches the operation via ``OperationRegistry``.
241
+ 5. Evaluates ``vcard_post`` gates (postcondition assertions).
242
+ 6. Seals the sandwich with pass/fail.
243
+ 7. Reports aggregate results.
244
+ """
245
+
246
+ def __init__(
247
+ self,
248
+ clm_root: str,
249
+ gate_evaluator: Any | None = None,
250
+ op_registry: OperationRegistry | None = None,
251
+ ) -> None:
252
+ self.clm_root = clm_root
253
+ # Sprint 132.1: GateEvaluator import moved to cross_cutting/__init__.py;
254
+ # import here to avoid circular dependency at module load
255
+ from clm.cross_cutting.vcard import GateEvaluator
256
+ self.gates = gate_evaluator or GateEvaluator()
257
+ self.ops = op_registry or OperationRegistry()
258
+
259
+ def run(self, clm_file: str) -> int:
260
+ """Execute all pending cases from a Face B manifest.
261
+
262
+ Returns 0 if every case passes, 1 otherwise.
263
+ """
264
+ import yaml
265
+
266
+ test_harness_path = os.path.join(self.clm_root, "tests", "00_microkernel")
267
+ if test_harness_path not in sys.path:
268
+ sys.path.insert(0, test_harness_path)
269
+
270
+ import test_utils
271
+
272
+ from clm.cross_cutting.vcard import VCardSandwich
273
+ from clm.layer0.context import CLMContext
274
+
275
+ if _classifier_hook is not None:
276
+ classify_clm, detect_dialect = _classifier_hook
277
+ elif _classifier_hook_resolver is not None:
278
+ hook = _classifier_hook_resolver()
279
+ classify_clm, detect_dialect = hook if hook else (lambda *a, **k: None, lambda *a, **k: None)
280
+ else:
281
+ classify_clm, detect_dialect = (lambda *a, **k: None, lambda *a, **k: None)
282
+
283
+ if not os.path.exists(clm_file):
284
+ _logger.error(f"FATAL: CLM manifest file not found at {clm_file}")
285
+ return 1
286
+
287
+ with open(clm_file, encoding="utf-8") as f:
288
+ manifest = yaml.safe_load(f)
289
+
290
+ clm_block = manifest.get("clm", manifest)
291
+ pending_cases = clm_block.get("pending_cases", [])
292
+
293
+ overall_failed = 0
294
+
295
+ for case in pending_cases:
296
+ rc = self._run_case(
297
+ case, test_utils, CLMDB, CLMRepository, CLMContext,
298
+ VCardSandwich, classify_clm, detect_dialect,
299
+ )
300
+ if rc != 0:
301
+ overall_failed += 1
302
+
303
+ if overall_failed == 0:
304
+ _logger.info("All dynamic Face B assertions verified successfully!")
305
+ return 0
306
+ else:
307
+ _logger.error(f"Face B verification failed: {overall_failed} test suite(s) had errors.")
308
+ return 1
309
+
310
+ def _run_case(
311
+ self, case: dict, test_utils: Any,
312
+ CLMDB: type, CLMRepository: type, CLMContext: type,
313
+ VCardSandwich: type, classify_clm: Callable, detect_dialect: Callable,
314
+ ) -> int:
315
+ """Execute a single pending case. Returns 0 on success, 1 on failure.
316
+
317
+ Sprint 128.5: Uses a unified ``CelStore`` for both pre and post gates
318
+ (progressive enrichment).
319
+ Sprint 130.2: Adds Phase 0 (verify_test_file expansion) and passes
320
+ ``store=`` to ``seal()`` so ``flush_action_log()`` persists the
321
+ action_log to ``execution_log.db``.
322
+ """
323
+ from clm.cross_cutting.cel_store import CelStore, EnvSlice, StateSlice
324
+
325
+ given = case.get("given", {})
326
+ step_seq = given.get("step_sequence")
327
+ inputs = given.get("inputs", {})
328
+
329
+ when = case.get("when", {})
330
+ operation = when.get("operation")
331
+
332
+ then = case.get("then", {})
333
+ assertions = then.get("assertions", {})
334
+ expected_outputs = then.get("outputs", {})
335
+
336
+ suite = test_utils.CLMTestSuite(f"Test Suite: {operation} (Step {step_seq})")
337
+
338
+ # ---- 0. Dynamic Gate Expansion (Sprint 130.2) ---------------------
339
+ # If verify_test_file is declared, expand it into vcard_pre +
340
+ # vcard_post gate blocks before evaluation. User-defined gates
341
+ # take precedence (prepended, not overwritten).
342
+ verify_file = then.get("verify_test_file")
343
+ if verify_file:
344
+ expanded = _expand_verify_test_file(verify_file, operation)
345
+ for gate_key in ("vcard_pre", "vcard_post"):
346
+ if gate_key not in assertions:
347
+ assertions[gate_key] = []
348
+ assertions[gate_key] = expanded[gate_key] + assertions[gate_key]
349
+
350
+ # ---- A. VCard Pre-Gate (minimal store) -----------------------------
351
+ store = CelStore(
352
+ state=StateSlice(inputs=inputs),
353
+ env=EnvSlice(
354
+ clm_root=self.clm_root,
355
+ os=os, sys=sys, time=time, hashlib=hashlib, str=str,
356
+ ),
357
+ )
358
+
359
+ for pre_item in assertions.get("vcard_pre", []):
360
+ if not self.gates.evaluate_pre(pre_item, store.to_dict(), suite):
361
+ suite.report_results()
362
+ return 1
363
+
364
+ # ---- B. Sandbox + VCardSandwich (Sprint 133.4: via thunk()) ------
365
+ with test_utils.CLMTestSandbox(self.clm_root, copy_schema=True) as tmp_dir:
366
+ db = CLMDB(tmp_dir)
367
+ ctx = CLMContext(root=tmp_dir, db=db, zero_fs=False)
368
+ repo = CLMRepository(db, tmp_dir)
369
+
370
+ agent_did = default_agent_did()
371
+
372
+ # Sprint 133.4: dispatch_fn replaces manual sandwich.__enter__/seal.
373
+ def _dispatch_fn(sandwich, store_arg):
374
+ step_passed = True
375
+ error_msg = ""
376
+ rc = 0
377
+ try:
378
+ rc = self.ops.dispatch(operation, tmp_dir)
379
+ except Exception as e:
380
+ step_passed = False
381
+ error_msg = str(e)
382
+ suite.tu_fail(f"Exception during transition execution: {e}")
383
+
384
+ # ---- D. VCard Post-Gate (enriched store) -----------------
385
+ from clm.cross_cutting.cel_store import build_store
386
+ post_store = build_store(
387
+ inputs=inputs, outputs=expected_outputs, rc=rc,
388
+ tmp_dir=tmp_dir, db=db, ctx=ctx, repo=repo,
389
+ classify_clm=classify_clm, detect_dialect=detect_dialect,
390
+ clm_root=self.clm_root,
391
+ )
392
+
393
+ for post_item in assertions.get("vcard_post", []):
394
+ if not self.gates.evaluate_post(post_item, post_store.to_dict(), suite):
395
+ step_passed = False
396
+
397
+ if suite.failed > 0 or not step_passed:
398
+ return 1, f"Verification failed: {error_msg or 'Suite assertions failed.'}"
399
+ return 0, "success"
400
+
401
+ from clm.cross_cutting.vcard import thunk
402
+ exit_code, _ = thunk(
403
+ store=None, action={}, ctx=ctx, operation=operation,
404
+ agent_did=agent_did,
405
+ dispatch_fn=_dispatch_fn,
406
+ )
407
+
408
+ if exit_code != 0:
409
+ suite.report_results()
410
+ return 1
411
+
412
+ suite.report_results()
413
+ return 0
414
+
415
+
416
+ # ---------------------------------------------------------------------------
417
+ # Public API
418
+ # ---------------------------------------------------------------------------
419
+
420
+ def run_balanced_expectations(clm_root: str, clm_file: str) -> int:
421
+ """Run all pending_cases from a Face B (Balanced Expectations) manifest.
422
+
423
+ This is the public entry point. Internally it creates a
424
+ :class:`BalancedRunner` with default gates and operations, then
425
+ delegates to :meth:`BalancedRunner.run`.
426
+ """
427
+ runner = BalancedRunner(clm_root)
428
+ return runner.run(clm_file)
429
+
430
+
431
+ # ---------------------------------------------------------------------------
432
+ # Absorbed re-exports — MOVED to cross_cutting/__init__.py in Sprint 132.1
433
+ # (facade inversion: pcard/ no longer imports upward into layer0/1/2)
434
+ # ---------------------------------------------------------------------------
@@ -0,0 +1,71 @@
1
+ """Declarative CLM Operation Registry (Sprint 179).
2
+
3
+ Replaces string-patched exec() with a strongly-typed, decorator-based dispatch mechanism.
4
+ Supports command aliases, metadata inspection, and isolated context injection.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import Callable
10
+ from typing import Any
11
+
12
+ from clm.cross_cutting.errors import OperationNotFoundError
13
+ from clm.layer0.context import CLMContext
14
+
15
+ _OPERATION_REGISTRY: dict[str, Callable[[list[str], CLMContext], int]] = {}
16
+ _OPERATION_METADATA: dict[str, dict[str, Any]] = {}
17
+
18
+
19
+ def clm_operation(
20
+ name: str,
21
+ *,
22
+ aliases: list[str] | None = None,
23
+ description: str = "",
24
+ ) -> Callable:
25
+ """Decorator to register a function as a CLM CLI / evaluator operation."""
26
+
27
+ def decorator(
28
+ fn: Callable[[list[str], CLMContext], int]
29
+ ) -> Callable[[list[str], CLMContext], int]:
30
+ _OPERATION_REGISTRY[name] = fn
31
+ meta = {
32
+ "name": name,
33
+ "description": description,
34
+ "aliases": aliases or [],
35
+ "fn_name": fn.__name__,
36
+ "module": fn.__module__,
37
+ }
38
+ _OPERATION_METADATA[name] = meta
39
+ if aliases:
40
+ for alias in aliases:
41
+ _OPERATION_REGISTRY[alias] = fn
42
+ _OPERATION_METADATA[alias] = meta
43
+ return fn
44
+
45
+ return decorator
46
+
47
+
48
+ def dispatch_operation(
49
+ name: str,
50
+ args: list[str] | None = None,
51
+ ctx: CLMContext | None = None,
52
+ ) -> int:
53
+ """Dispatch a registered operation by name with typed arguments and isolated context."""
54
+ fn = _OPERATION_REGISTRY.get(name)
55
+ if not fn:
56
+ available = ", ".join(sorted(set(_OPERATION_REGISTRY.keys())))
57
+ raise OperationNotFoundError(
58
+ f"Unknown CLM operation: '{name}'. Available operations: [{available}]"
59
+ )
60
+ context = ctx or CLMContext.current()
61
+ return fn(args or [], context)
62
+
63
+
64
+ def get_registered_operations() -> list[str]:
65
+ """Return all unique registered operation names."""
66
+ return sorted(set(_OPERATION_REGISTRY.keys()))
67
+
68
+
69
+ def get_operation_metadata(name: str) -> dict[str, Any] | None:
70
+ """Return metadata dict for an operation name or alias."""
71
+ return _OPERATION_METADATA.get(name)
@@ -0,0 +1,84 @@
1
+ """Resource resolution module for CLM packages and developmental workspaces.
2
+
3
+ Provides robust resolution of bundled schema definitions, SQL scripts, and
4
+ configuration templates via PEP 302/366/3002 importlib.resources standards with
5
+ seamless fallback to local source tree layouts during development.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import importlib.resources
11
+ import os
12
+ from pathlib import Path
13
+
14
+
15
+ def get_schema_path(filename: str = "mcard_schema.sql") -> Path:
16
+ """Resolve the absolute filesystem path for a schema file.
17
+
18
+ Search priority:
19
+ 1. Bundled package resources in `clm.schemas` (wheel/installed mode)
20
+ 2. Package-relative path `clm/schemas/`
21
+ 3. Monorepo workspace `CLM_ROOT/types/schemas/` or `types/schemas/`
22
+ 4. Parent directory `../types/schemas/`
23
+
24
+ Args:
25
+ filename: Name of the schema file (e.g. 'mcard_schema.sql', 'cel_schema.yaml').
26
+
27
+ Returns:
28
+ Path object pointing to the existing schema file.
29
+
30
+ Raises:
31
+ FileNotFoundError: If the schema file cannot be located across all candidates.
32
+ """
33
+ # 1. Try importlib.resources (installed wheel package mode)
34
+ try:
35
+ resource_ref = importlib.resources.files("clm.schemas").joinpath(filename)
36
+ # In Python 3.9+, Traversable might be a concrete path or in a zip
37
+ candidate = Path(str(resource_ref))
38
+ if candidate.is_file():
39
+ return candidate
40
+ except Exception:
41
+ pass
42
+
43
+ # 2. Try relative to this file's package tree: kernel/scripts/clm/schemas/
44
+ pkg_schema = Path(__file__).resolve().parent.parent / "schemas" / filename
45
+ if pkg_schema.is_file():
46
+ return pkg_schema
47
+
48
+ # 3. Try CLM_ROOT environment variable or current directory
49
+ clm_root_env = os.environ.get("CLM_ROOT")
50
+ if clm_root_env:
51
+ root_path = Path(clm_root_env).resolve()
52
+ candidate = root_path / "types" / "schemas" / filename
53
+ if candidate.is_file():
54
+ return candidate
55
+ candidate = root_path / "clm" / "types" / "schemas" / filename
56
+ if candidate.is_file():
57
+ return candidate
58
+
59
+ # 4. Try current working directory and parent paths
60
+ cwd = Path.cwd().resolve()
61
+ for base in [cwd, cwd.parent, cwd.parent.parent]:
62
+ candidate = base / "types" / "schemas" / filename
63
+ if candidate.is_file():
64
+ return candidate
65
+ candidate = base / "clm" / "types" / "schemas" / filename
66
+ if candidate.is_file():
67
+ return candidate
68
+
69
+ raise FileNotFoundError(
70
+ f"CLM schema '{filename}' could not be resolved via importlib.resources or workspace search."
71
+ )
72
+
73
+
74
+ def get_schema_content(filename: str = "mcard_schema.sql") -> str:
75
+ """Read and return the text contents of a CLM schema file.
76
+
77
+ Args:
78
+ filename: Name of the schema file.
79
+
80
+ Returns:
81
+ String content of the schema file decoded as UTF-8.
82
+ """
83
+ path = get_schema_path(filename)
84
+ return path.read_text(encoding="utf-8")
@@ -0,0 +1,44 @@
1
+ """Cryptographic secret container with explicit zeroization and RAII protection (Sprint 176).
2
+
3
+ Prevents accidental key leaks into log files or tracebacks via custom __repr__ and __str__,
4
+ and scrubs memory buffer with null bytes on drop or context exit.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import ctypes
10
+ from typing import Self
11
+
12
+
13
+ class SecretBytes:
14
+ """Container for sensitive cryptographic material with explicit zeroization."""
15
+
16
+ def __init__(self, data: bytes) -> None:
17
+ self._buf = bytearray(data)
18
+
19
+ def reveal(self) -> bytes:
20
+ """Access raw bytes. Caller should avoid assigning to long-lived variables."""
21
+ if not self._buf:
22
+ raise ValueError("SecretBytes buffer has been zeroized")
23
+ return bytes(self._buf)
24
+
25
+ def zeroize(self) -> None:
26
+ """Explicitly overwrite buffer memory with null bytes."""
27
+ if self._buf:
28
+ ctypes.memset((ctypes.c_char * len(self._buf)).from_buffer(self._buf), 0, len(self._buf))
29
+ self._buf.clear()
30
+
31
+ def __enter__(self) -> Self:
32
+ return self
33
+
34
+ def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> None:
35
+ self.zeroize()
36
+
37
+ def __del__(self) -> None:
38
+ self.zeroize()
39
+
40
+ def __repr__(self) -> str:
41
+ return "<SecretBytes [REDACTED]>"
42
+
43
+ def __str__(self) -> str:
44
+ return "<SecretBytes [REDACTED]>"