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,716 @@
1
+ """PCard Model (Control Plane) - Implementation of LENS/CHART values.
2
+
3
+ This module defines the PCard, which represents the execution unit in the DOTS framework.
4
+ PCards are MCards that contain a valid CLM (Cubical Logic Model) specification.
5
+
6
+ Categorical Foundation:
7
+ PCard is a Strong Profunctor: P: A^op × B → Set
8
+
9
+ This means PCard is:
10
+ - Contravariant in its input (A^op): Can accept MORE general inputs
11
+ - Covariant in its output (B): Can produce MORE specific outputs
12
+
13
+ The "Strong" property means PCard supports:
14
+ - first: P(A, B) → P(C × A, C × B) (threading context through)
15
+ - second: P(A, B) → P(A × C, B × C) (preserving additional structure)
16
+
17
+ Composition via Coend:
18
+ Two PCards P and Q compose via the Coend (∫ᴮ):
19
+
20
+ (P ⨾ Q)(A, C) = ∫ᴮ P(A, B) × Q(B, C)
21
+
22
+ The Coend "integrates out" the intermediate type B by:
23
+ 1. Finding all compatible B-typed interfaces
24
+ 2. Identifying outputs of P with inputs of Q
25
+ 3. Producing a new PCard that chains the transformations
26
+
27
+ This is implemented by the `then()` method (sequential composition).
28
+ """
29
+
30
+ from typing import TYPE_CHECKING, Any
31
+
32
+ import yaml
33
+
34
+ from clm.layer0.model.card import MCard
35
+ from clm.layer0.model.dots import DOTSMetadata, create_pcard_dots_metadata
36
+
37
+ if TYPE_CHECKING:
38
+ from clm.layer0.model.vcard import VCard
39
+
40
+
41
+ class PCard(MCard):
42
+ """PCard - The Control Plane unit (Lens + Chart).
43
+
44
+ A PCard is an MCard whose content is a valid CLM specification.
45
+
46
+ =============================================================================
47
+ CATEGORICAL FOUNDATIONS (Strong Profunctor)
48
+ =============================================================================
49
+
50
+ PCard implements the Strong Profunctor pattern from category theory:
51
+
52
+ **Profunctor Definition**:
53
+ P: A^op × B → Set
54
+
55
+ Where:
56
+ - A^op denotes contravariance in input types (accepts MORE general)
57
+ - B denotes covariance in output types (produces MORE specific)
58
+ - Set is the category of sets (our value space)
59
+
60
+ **Strong Profunctor Operations**:
61
+ - `dimap(f, g)`: Transform both input (contravariant) and output (covariant)
62
+ - `first()`: Thread additional context through: P(A,B) → P(C×A, C×B)
63
+ - `second()`: Preserve additional structure: P(A,B) → P(A×C, B×C)
64
+
65
+ **Intuition**:
66
+ PCard defines a transformation that can:
67
+ - Accept inputs of type A (or any supertype, due to contravariance)
68
+ - Produce outputs of type B (or any subtype, due to covariance)
69
+ - Carry additional context through the transformation (Strong property)
70
+
71
+ =============================================================================
72
+ COMPOSITION VIA COEND
73
+ =============================================================================
74
+
75
+ Two PCards compose via the Coend (categorical integral):
76
+
77
+ (P ⨾ Q)(A, C) = ∫ᴮ P(A, B) × Q(B, C)
78
+
79
+ Where:
80
+ - ∫ᴮ is the Coend over the intermediate type B
81
+ - P(A, B) is the first PCard (input A, output B)
82
+ - Q(B, C) is the second PCard (input B, output C)
83
+ - The result is a new PCard from A to C
84
+
85
+ **Coend Interpretation**:
86
+ The Coend "glues together" all compatible B-typed interfaces:
87
+ 1. For each possible B, find P's outputs and Q's inputs
88
+ 2. Identify P's output with Q's input (via hash matching)
89
+ 3. The quotient identifies equivalent compositions
90
+
91
+ **Implementation**:
92
+ `then()` implements Coend composition:
93
+ - Creates a new CLM that chains the two PCards
94
+ - The intermediate B is represented by content hashes
95
+ - Type compatibility is verified at execution time by PTR
96
+
97
+ =============================================================================
98
+ SMC STRUCTURE (Symmetric Monoidal Category)
99
+ =============================================================================
100
+
101
+ PCard composition forms a Symmetric Monoidal Category:
102
+
103
+ - **Objects**: Content types (MCard content hashes as type witnesses)
104
+ - **Morphisms**: PCards (transformations between types)
105
+ - **Identity**: The "pass-through" PCard (`id_A: A → A`)
106
+ - **Composition**: Sequential chaining via `then()` (;)
107
+ - **Tensor Product**: Parallel composition via `and_also()` (⊗)
108
+ - **Symmetry**: Port swapping via `swap()` (σ)
109
+
110
+ **Coherence Laws** (satisfied by implementation):
111
+ - Associativity: (f ; g) ; h = f ; (g ; h)
112
+ - Identity: id ; f = f = f ; id
113
+ - Tensor associativity: (A ⊗ B) ⊗ C ≅ A ⊗ (B ⊗ C)
114
+ - Symmetry: σ ∘ σ = id, and σ is natural
115
+
116
+ =============================================================================
117
+ OTHER ROLES
118
+ =============================================================================
119
+
120
+ Petri Net (UPTV):
121
+ - Role: Transition (Process)
122
+ - Consumes VCards (input tokens), produces VCards (output tokens)
123
+ - Fire condition: All input places have required tokens
124
+
125
+ DOTS Vocabulary:
126
+ - LENS: Tight morphism (Abstract ↔ Concrete coherence)
127
+ - CHART: Loose morphism (Interaction pattern wiring)
128
+
129
+ CLM Triad Structure:
130
+ - Abstract (A): Specification (Thesis) - WHAT
131
+ - Concrete (C): Implementation (Antithesis) - HOW
132
+ - Balanced (B): Evidence/Tests (Synthesis) - PROOF
133
+ """
134
+
135
+ def __init__(self, content: str | bytes, hash_function: str | Any = "sha256"):
136
+ """Initialize a PCard.
137
+
138
+ Args:
139
+ content: The CLM YAML string.
140
+ hash_function: Hash function to use.
141
+
142
+ Raises:
143
+ ValueError: If content is not valid YAML or valid CLM structure.
144
+ """
145
+ super().__init__(content, hash_function)
146
+ self._parsed_clm = self._validate_and_parse()
147
+
148
+ def _validate_and_parse(self) -> dict[str, Any]:
149
+ """Validate content is structured data and return parsed dict.
150
+
151
+ This method is the canonical parse hook for the MCard → PCard → VCard
152
+ hierarchy. Subclasses (notably **VCard**) override this method to act
153
+ as the *guard* (precondition) — accepting additional content formats
154
+ (e.g., JSON VCard Sandwich) and providing graceful fallbacks for
155
+ non-dict content.
156
+
157
+ For a pure PCard instance the content MUST be valid YAML that
158
+ deserialises to a ``dict``.
159
+ """
160
+ try:
161
+ content_str = self.get_content(as_text=True)
162
+ clm = yaml.safe_load(content_str)
163
+
164
+ if not isinstance(clm, dict):
165
+ raise ValueError("PCard content must be a YAML dictionary")
166
+
167
+ return clm
168
+ except yaml.YAMLError as e:
169
+ raise ValueError(f"Invalid YAML content for PCard: {e}") from e
170
+
171
+ def get_dots_metadata(self) -> DOTSMetadata:
172
+ """Get DOTS metadata for this PCard."""
173
+ tight_refs = []
174
+ loose_refs = []
175
+
176
+ # Extract dependencies if they exist in standard CLM fields
177
+ for key in ["tight_deps", "dependencies"]:
178
+ if key in self._parsed_clm and isinstance(self._parsed_clm[key], list):
179
+ tight_refs.extend(self._parsed_clm[key])
180
+
181
+ for key in ["loose_deps", "alternatives"]:
182
+ if key in self._parsed_clm and isinstance(self._parsed_clm[key], list):
183
+ loose_refs.extend(self._parsed_clm[key])
184
+
185
+ return create_pcard_dots_metadata(
186
+ spec_hash=self.hash,
187
+ tight_refs=tight_refs if tight_refs else None,
188
+ loose_refs=loose_refs if loose_refs else None,
189
+ )
190
+
191
+ @property
192
+ def clm(self) -> dict[str, Any]:
193
+ """Get the parsed CLM dictionary."""
194
+ return self._parsed_clm
195
+
196
+ # -------------------------------------------------------------------------
197
+ # UPTV CLM Triad Accessors (A x C x B)
198
+ # -------------------------------------------------------------------------
199
+
200
+ def _get_section(
201
+ self, section_name: str, aliases: list[str]
202
+ ) -> dict[str, Any] | None:
203
+ """Helper to retrieve section from root or nested 'clm' or aliases."""
204
+ # 1. Check root
205
+ val = self._parsed_clm.get(section_name)
206
+ if val:
207
+ return val
208
+
209
+ # 2. Check aliases at root
210
+ for alias in aliases:
211
+ val = self._parsed_clm.get(alias)
212
+ if val:
213
+ return val
214
+
215
+ # 3. Check inside 'clm' dict (nested structure)
216
+ clm_inner = self._parsed_clm.get("clm")
217
+ if isinstance(clm_inner, dict):
218
+ val = clm_inner.get(section_name)
219
+ if val:
220
+ return val
221
+ for alias in aliases:
222
+ val = clm_inner.get(alias)
223
+ if val:
224
+ return val
225
+
226
+ return None
227
+
228
+ @property
229
+ def abstract(self) -> dict[str, Any] | None:
230
+ """Get the Abstract (A) section."""
231
+ return self._get_section("abstract", ["abstract_spec"])
232
+
233
+ @property
234
+ def concrete(self) -> dict[str, Any] | None:
235
+ """Get the Concrete (C) section."""
236
+ return self._get_section("concrete", ["concrete_impl", "impl"])
237
+
238
+ @property
239
+ def balanced(self) -> dict[str, Any] | None:
240
+ """Get the Balanced (B) section."""
241
+ return self._get_section("balanced", ["balanced_expectations", "expectations"])
242
+
243
+ # -------------------------------------------------------------------------
244
+ # Legacy Aliases (Strict Backward Compatibility)
245
+ # -------------------------------------------------------------------------
246
+
247
+ @property
248
+ def abstract_spec(self) -> dict[str, Any] | None:
249
+ """Legacy alias for abstract."""
250
+ return self.abstract
251
+
252
+ @property
253
+ def concrete_impl(self) -> dict[str, Any] | None:
254
+ """Legacy alias for concrete."""
255
+ return self.concrete
256
+
257
+ @property
258
+ def balanced_expectations(self) -> dict[str, Any] | None:
259
+ """Legacy alias for balanced."""
260
+ return self.balanced
261
+
262
+ # =========================================================================
263
+ # SMC ALGEBRAIC COMBINATORS (Profunctor Composition)
264
+ # =========================================================================
265
+ #
266
+ # These methods implement the Symmetric Monoidal Category structure,
267
+ # enabling algebraic composition of PCards as profunctors.
268
+ #
269
+ # Composition Laws (Categorical Coherence):
270
+ # - Associativity: (f.then(g)).then(h) ≡ f.then(g.then(h))
271
+ # - Identity: id.then(f) ≡ f ≡ f.then(id)
272
+ # - Tensor Associativity: (A ⊗ B) ⊗ C ≅ A ⊗ (B ⊗ C)
273
+ # - Symmetry Involution: swap().swap() ≡ id
274
+ # =========================================================================
275
+
276
+ def then(self, other_pcard: "PCard") -> "PCard":
277
+ """Sequential Composition via Coend ($P ⨾ Q$).
278
+
279
+ Implements profunctor composition using the Coend formula:
280
+
281
+ (P ⨾ Q)(A, C) = ∫ᴮ P(A, B) × Q(B, C)
282
+
283
+ Where:
284
+ - self is P: A → B
285
+ - other_pcard is Q: B → C
286
+ - Result is P ⨾ Q: A → C
287
+
288
+ The Coend (∫ᴮ) "integrates out" the intermediate type B by:
289
+ 1. Matching P's output type with Q's input type
290
+ 2. Creating a chain where P's result feeds into Q
291
+ 3. The composition is associative: (P ⨾ Q) ⨾ R = P ⨾ (Q ⨾ R)
292
+
293
+ In PTR execution:
294
+ - P is executed first (prep → exec → post)
295
+ - P's output VCard becomes Q's input VCard
296
+ - Q is executed second
297
+ - Final result is Q's output VCard
298
+
299
+ Args:
300
+ other_pcard: The PCard to execute after this one (Q in P ⨾ Q).
301
+
302
+ Returns:
303
+ A new PCard representing the composed profunctor (P ⨾ Q).
304
+ """
305
+ # Create a new CLM that composes the two
306
+ new_clm = {
307
+ "chapter": {
308
+ "id": f"composed_{self.hash[:8]}_{other_pcard.hash[:8]}",
309
+ "title": "Sequentially Composed Function",
310
+ "goal": f"Compose {self.hash} then {other_pcard.hash}",
311
+ },
312
+ "clm": {
313
+ "abstract": {
314
+ "type": "sequential_composition",
315
+ "coend_formula": "∫ᴮ P(A,B) × Q(B,C)",
316
+ "steps": [self.hash, other_pcard.hash],
317
+ },
318
+ "concrete": {
319
+ "runtime": "ptr",
320
+ "operation": "compose_sequential",
321
+ "steps": [self.hash, other_pcard.hash],
322
+ },
323
+ },
324
+ }
325
+ return PCard(yaml.dump(new_clm), self.hash_function)
326
+
327
+ def and_also(self, other_pcard: "PCard") -> "PCard":
328
+ r"""Tensor Product ($A \otimes B$).
329
+
330
+ Runs this PCard and other_pcard in parallel.
331
+
332
+ Args:
333
+ other_pcard: The PCard to execute in parallel.
334
+
335
+ Returns:
336
+ A new PCard representing the parallel execution.
337
+ """
338
+ new_clm = {
339
+ "chapter": {
340
+ "id": f"parallel_{self.hash[:8]}_{other_pcard.hash[:8]}",
341
+ "title": "Parallel Function",
342
+ "goal": f"Run {self.hash} and {other_pcard.hash} in parallel",
343
+ },
344
+ "clm": {
345
+ "abstract": {
346
+ "type": "tensor_product",
347
+ "left": self.hash,
348
+ "right": other_pcard.hash,
349
+ },
350
+ "concrete": {
351
+ "runtime": "ptr",
352
+ "operation": "compose_parallel",
353
+ "components": [self.hash, other_pcard.hash],
354
+ },
355
+ },
356
+ }
357
+ return PCard(yaml.dump(new_clm), self.hash_function)
358
+
359
+ def swap(self) -> "PCard":
360
+ r"""Symmetry ($\sigma$).
361
+
362
+ Swaps the input/output ports of a tensor product.
363
+
364
+ Returns:
365
+ A new PCard with swapped inputs/outputs.
366
+ """
367
+ new_clm = {
368
+ "chapter": {
369
+ "id": f"swapped_{self.hash[:8]}",
370
+ "title": "Swapped Function",
371
+ "goal": f"Swap inputs/outputs of {self.hash}",
372
+ },
373
+ "clm": {
374
+ "abstract": {"type": "symmetry_swap", "target": self.hash},
375
+ "concrete": {
376
+ "runtime": "ptr",
377
+ "operation": "apply_symmetry",
378
+ "target": self.hash,
379
+ },
380
+ },
381
+ }
382
+ return PCard(yaml.dump(new_clm), self.hash_function)
383
+
384
+ # =========================================================================
385
+ # Universal Tooling Interface
386
+ # =========================================================================
387
+
388
+ def verify(self) -> dict[str, Any]:
389
+ """Run the Balanced Expectations (Proof).
390
+
391
+ Returns:
392
+ Dict containing verification results.
393
+ """
394
+ # In a real implementation, this would trigger the Verifier component
395
+ # For now, return the balanced spec as a "proof plan"
396
+ return {
397
+ "status": "pending_verification",
398
+ "proof_plan": self.balanced,
399
+ "target": self.hash,
400
+ }
401
+
402
+ def profile(self) -> dict[str, Any]:
403
+ """Run with instrumentation (eBPF/Tracing).
404
+
405
+ Returns:
406
+ Dict containing performance metrics.
407
+ """
408
+ return {
409
+ "status": "profiling_ready",
410
+ "target": self.hash,
411
+ "instrumentation": "standard",
412
+ }
413
+
414
+ def debug(self) -> dict[str, Any]:
415
+ """Run in Operative mode (Step-by-step).
416
+
417
+ Returns:
418
+ Dict containing debug session info.
419
+ """
420
+ return {
421
+ "status": "debug_session_created",
422
+ "mode": "operative",
423
+ "target": self.hash,
424
+ }
425
+
426
+ def explain(self) -> dict[str, Any]:
427
+ """Return documentation/explanation.
428
+
429
+ Returns:
430
+ Dict containing abstract spec and narrative.
431
+ """
432
+ return {
433
+ "abstract": self.abstract,
434
+ "narrative": self._parsed_clm.get("chapter", {}),
435
+ "dots_metadata": self.get_dots_metadata().__dict__,
436
+ }
437
+
438
+ def get_input_vcard_refs(self) -> list[dict[str, Any]]:
439
+ """Get input VCard references (Pre-set: •t).
440
+
441
+ These represent the preconditions that must be satisfied before
442
+ this PCard (Transition) can fire.
443
+
444
+ Returns:
445
+ List of input VCard references from CLM specification
446
+ """
447
+ refs = []
448
+ clm = self._parsed_clm
449
+
450
+ # Check for explicit input_vcards in CLM
451
+ input_vcards = (
452
+ clm.get("input_vcards") or clm.get("preconditions") or clm.get("requires")
453
+ )
454
+
455
+ if isinstance(input_vcards, list):
456
+ for ref in input_vcards:
457
+ if isinstance(ref, str):
458
+ refs.append({"handle": ref})
459
+ elif isinstance(ref, dict) and "handle" in ref:
460
+ refs.append(
461
+ {
462
+ "handle": ref["handle"],
463
+ "expected_hash": ref.get("hash")
464
+ or ref.get("expected_hash"),
465
+ "purpose": ref.get("purpose"),
466
+ }
467
+ )
468
+
469
+ # Also check verification.pcard_refs for authentication requirements
470
+ verification = clm.get("clm", {}).get("verification") or clm.get("verification")
471
+ if verification:
472
+ pcard_refs = verification.get("pcard_refs", [])
473
+ for ref in pcard_refs:
474
+ if isinstance(ref, str):
475
+ refs.append({"handle": f"auth://{ref}", "purpose": "authenticate"})
476
+ elif isinstance(ref, dict) and "hash" in ref:
477
+ refs.append(
478
+ {
479
+ "handle": f"auth://{ref['hash']}",
480
+ "expected_hash": ref["hash"],
481
+ "purpose": ref.get("purpose", "authenticate"),
482
+ }
483
+ )
484
+
485
+ return refs
486
+
487
+ def get_output_vcard_specs(self) -> list[dict[str, Any]]:
488
+ """Get output VCard specifications (Post-set: t•).
489
+
490
+ These define what VCards (Tokens) this PCard produces when fired.
491
+
492
+ Returns:
493
+ List of output VCard specifications
494
+ """
495
+ specs = []
496
+ clm = self._parsed_clm
497
+
498
+ # Check for explicit output_vcards in CLM
499
+ output_vcards = (
500
+ clm.get("output_vcards") or clm.get("postconditions") or clm.get("produces")
501
+ )
502
+
503
+ if isinstance(output_vcards, list):
504
+ for spec in output_vcards:
505
+ if isinstance(spec, str):
506
+ specs.append({"handle": spec, "type": "result"})
507
+ elif isinstance(spec, dict) and "handle" in spec:
508
+ specs.append(
509
+ {
510
+ "handle": spec["handle"],
511
+ "type": spec.get("type", "result"),
512
+ "metadata": spec.get("metadata"),
513
+ }
514
+ )
515
+
516
+ # Default: produce a verification VCard at balanced handle
517
+ if not specs:
518
+ chapter = clm.get("chapter")
519
+ if chapter and isinstance(chapter, dict) and chapter.get("title"):
520
+ import re
521
+
522
+ safe_name = re.sub(r"[^a-z0-9]", "_", chapter["title"].lower())
523
+ specs.append(
524
+ {"handle": f"{safe_name}/balanced", "type": "verification"}
525
+ )
526
+
527
+ return specs
528
+
529
+ def get_transition_handle(self) -> str:
530
+ """Get the canonical handle for this PCard (Transition).
531
+
532
+ Returns:
533
+ Handle string in form `{module}/{function}/spec`
534
+ """
535
+ chapter = self._parsed_clm.get("chapter")
536
+ if chapter and isinstance(chapter, dict) and "id" in chapter:
537
+ title = chapter.get("title")
538
+ if title:
539
+ import re
540
+
541
+ safe_name = re.sub(r"[^a-z0-9]", "_", title.lower())
542
+ else:
543
+ safe_name = f"chapter_{chapter['id']}"
544
+ return f"{safe_name}/spec"
545
+
546
+ # Fallback to hash-based handle
547
+ return f"hash/{self.hash[:16]}/spec"
548
+
549
+ def get_balanced_handle(self) -> str:
550
+ """Get the balanced expectations handle for this PCard.
551
+
552
+ This is where verification history is tracked in handle_history.
553
+
554
+ Returns:
555
+ Handle string for balanced expectations
556
+ """
557
+ spec_handle = self.get_transition_handle()
558
+ return spec_handle.replace("/spec", "/balanced")
559
+
560
+ def can_fire(self, available_vcards: dict[str, str]) -> dict[str, Any]:
561
+ """Check if this PCard (Transition) can fire given the available VCards.
562
+
563
+ A transition can fire when all input VCards (preconditions) are present.
564
+
565
+ Args:
566
+ available_vcards: Dict of handle -> VCard hash
567
+
568
+ Returns:
569
+ Dict containing 'can_fire' (bool) and 'missing' (list of handles)
570
+ """
571
+ input_refs = self.get_input_vcard_refs()
572
+ missing = []
573
+
574
+ for ref in input_refs:
575
+ handle = ref["handle"]
576
+ expected_hash = ref.get("expected_hash")
577
+
578
+ vcard_hash = available_vcards.get(handle)
579
+ if not vcard_hash:
580
+ missing.append(handle)
581
+ elif expected_hash and vcard_hash != expected_hash:
582
+ missing.append(f"{handle} (hash mismatch)")
583
+
584
+ return {"can_fire": len(missing) == 0, "missing": missing}
585
+
586
+ def get_runtime(self) -> str:
587
+ """Get the runtime required for this PCard.
588
+
589
+ Returns:
590
+ Runtime name (e.g., 'javascript', 'python', 'lean')
591
+ """
592
+ clm_config = self._parsed_clm.get("clm", {}).get("concrete")
593
+ concrete = self._parsed_clm.get("concrete")
594
+
595
+ if clm_config and "runtime" in clm_config:
596
+ return clm_config["runtime"]
597
+ if concrete and "runtime" in concrete:
598
+ return concrete["runtime"]
599
+
600
+ # Default or try logic_source detection?
601
+ return "javascript" # Default in JS implementation too
602
+
603
+ def is_multi_runtime(self) -> bool:
604
+ """Check if this is a multi-runtime PCard.
605
+
606
+ Returns:
607
+ True if this PCard supports multiple runtimes
608
+ """
609
+ clm_config = self._parsed_clm.get("clm", {}).get("concrete")
610
+ concrete = self._parsed_clm.get("concrete")
611
+
612
+ config = clm_config or concrete
613
+ return (
614
+ config
615
+ and isinstance(config.get("runtimes_config"), list)
616
+ and len(config["runtimes_config"]) > 1
617
+ )
618
+
619
+ # =========================================================================
620
+ # VCard Sandwich Boundary Specifications
621
+ # =========================================================================
622
+
623
+ def get_pre_vcard_spec(self) -> dict[str, Any]:
624
+ """Get the precondition VCard specification (V_pre boundary).
625
+
626
+ Extracts the pre-condition evaluator definition from the CLM
627
+ abstract.preconditions. This defines what the PTR engine must
628
+ check BEFORE executing the Evaluation Map.
629
+
630
+ Returns:
631
+ Dict with precondition specification:
632
+ - conditions: list of precondition strings/dicts
633
+ - type: "function_check" | "schema_check" | "capability_check"
634
+ """
635
+ abstract = self.abstract or {}
636
+ preconditions = abstract.get("preconditions", [])
637
+
638
+ return {
639
+ "pcard_hash": self.hash,
640
+ "phase": "prep",
641
+ "conditions": preconditions if isinstance(preconditions, list) else [],
642
+ "type": self._classify_conditions(preconditions),
643
+ }
644
+
645
+ def get_post_vcard_spec(self) -> dict[str, Any]:
646
+ """Get the postcondition VCard specification (V_post boundary).
647
+
648
+ Extracts the post-condition evaluator definition from the CLM
649
+ abstract.postconditions. This defines what the PTR engine must
650
+ check AFTER executing the Evaluation Map.
651
+
652
+ Returns:
653
+ Dict with postcondition specification:
654
+ - conditions: list of postcondition strings/dicts
655
+ - type: "function_check" | "schema_check" | "capability_check"
656
+ """
657
+ abstract = self.abstract or {}
658
+ postconditions = abstract.get("postconditions", [])
659
+
660
+ return {
661
+ "pcard_hash": self.hash,
662
+ "phase": "post",
663
+ "conditions": postconditions if isinstance(postconditions, list) else [],
664
+ "type": self._classify_conditions(postconditions),
665
+ }
666
+
667
+ @staticmethod
668
+ def _classify_conditions(conditions: Any) -> str:
669
+ """Classify the type of boundary conditions."""
670
+ if not conditions or not isinstance(conditions, list):
671
+ return "none"
672
+ # Check if any condition references a function hash (content-addressed check)
673
+ for c in conditions:
674
+ if isinstance(c, dict):
675
+ if c.get("code_hash") or c.get("runtime"):
676
+ return "function_check"
677
+ if c.get("schema"):
678
+ return "schema_check"
679
+ if c.get("capability") or c.get("scope"):
680
+ return "capability_check"
681
+ return "declarative_check"
682
+
683
+ def create_vcard(
684
+ self,
685
+ vcard_class: type = None,
686
+ subject_did: str = "",
687
+ controller_pubkeys: list[str] | None = None,
688
+ capabilities: list[Any] | None = None,
689
+ external_refs: list[Any] | None = None,
690
+ managed_event_types: list[str] | None = None,
691
+ **kwargs: Any,
692
+ ) -> "VCard":
693
+ """Instantiate a VCard explicitly wrapping this PCard.
694
+
695
+ This establishes the PCard as the literal factory for its VCards,
696
+ ensuring that the `wrapped_pcard_hash` is permanently embedded into
697
+ the generated VCard's content structure.
698
+ """
699
+ if vcard_class is None:
700
+ # We must import inside the method to avoid circular imports,
701
+ # as VCard inherits from PCard.
702
+ from clm.layer0.model.vcard import VCard
703
+
704
+ vcard_class = VCard
705
+
706
+ # Instantiate the provided VCard class (or base VCard),
707
+ # automatically injecting this PCard's hash.
708
+ return vcard_class(
709
+ subject_did=subject_did,
710
+ controller_pubkeys=controller_pubkeys or [],
711
+ capabilities=capabilities or [],
712
+ external_refs=external_refs or [],
713
+ managed_event_types=managed_event_types or [],
714
+ wrapped_pcard_hash=self.hash,
715
+ **kwargs,
716
+ )