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,498 @@
1
+ import os
2
+ import shutil
3
+ import subprocess
4
+
5
+ import yaml
6
+
7
+ from clm.cross_cutting.clm_logger import get_logger
8
+ from clm.layer0.utils import get_bash_command
9
+
10
+ _logger = get_logger("clm.layer1.test_runner")
11
+
12
+
13
+ def test_type_system(clm_root: str) -> int:
14
+ """
15
+ Executes compliance assertions against the CLM type registry and yaml schemas.
16
+
17
+ Args:
18
+ clm_root (str): The workspace root directory.
19
+
20
+ Returns:
21
+ int: 0 if all tests pass, 1 otherwise.
22
+ """
23
+ print("======================================================")
24
+ print(" Test Suite: CLM Type System (Python Native)")
25
+ print("======================================================\n")
26
+
27
+ passed = 0
28
+ failed = 0
29
+
30
+ def _assert(desc, cond):
31
+ nonlocal passed, failed
32
+ if cond:
33
+ print(f" ✅ {desc}")
34
+ passed += 1
35
+ return True
36
+ else:
37
+ print(f" ❌ {desc}")
38
+ failed += 1
39
+ return False
40
+
41
+ all_types = [
42
+ "types/meta/a_mcard.yaml",
43
+ "types/meta/b_mcard.yaml",
44
+ "types/meta/c_mcard.yaml",
45
+ "types/primitives/string.yaml",
46
+ "types/primitives/integer.yaml",
47
+ "types/primitives/float.yaml",
48
+ "types/primitives/boolean.yaml",
49
+ "types/primitives/blob.yaml",
50
+ "types/primitives/list.yaml",
51
+ "types/primitives/map.yaml",
52
+ "types/runtime/agent.yaml",
53
+ "types/runtime/clmEval.yaml",
54
+ "types/runtime/evaluate.yaml"
55
+ ]
56
+
57
+ print("-- 1. Grammar Standard Compliance --")
58
+ for t in all_types:
59
+ full_path = os.path.join(clm_root, t)
60
+ name = os.path.splitext(os.path.basename(t))[0]
61
+ try:
62
+ with open(full_path, encoding="utf-8") as f:
63
+ data = yaml.safe_load(f)
64
+ clm_block = data.get("clm")
65
+ _assert(f"{name}: has clm: root wrapper", clm_block is not None)
66
+ if clm_block:
67
+ _assert(f"{name}: uses balanced_exp (not balanced_expc)", "balanced_exp" in clm_block and "balanced_expc" not in clm_block)
68
+ abstract = clm_block.get("abstract_spec", {})
69
+ sc = abstract.get("success_criteria")
70
+ _assert(f"{name}: success_criteria is a list", isinstance(sc, list))
71
+ except Exception as e:
72
+ _assert(f"{name}: failed to read or parse - {e}", False)
73
+
74
+ print("\n-- 2. Schema Sections --")
75
+ for t in all_types:
76
+ full_path = os.path.join(clm_root, t)
77
+ name = os.path.splitext(os.path.basename(t))[0]
78
+ try:
79
+ with open(full_path, encoding="utf-8") as f:
80
+ data = yaml.safe_load(f)
81
+ clm_block = data.get("clm")
82
+ schema = clm_block.get("concrete_impl", {}).get("schema") if clm_block else None
83
+ _assert(f"{name}: has schema section", schema is not None)
84
+ except Exception as e:
85
+ _assert(f"{name}: failed schema check - {e}", False)
86
+
87
+ print("\n-- 3. Type Registry --")
88
+
89
+ def resolve_type_path(clm_root, tname):
90
+ for tier in ("meta", "primitives", "runtime", "content", "transport", "codegen"):
91
+ candidate = os.path.join(clm_root, "types", tier, f"{tname}.yaml")
92
+ if os.path.exists(candidate):
93
+ return candidate
94
+ return None
95
+
96
+ a_mcard_path = resolve_type_path(clm_root, "a_mcard")
97
+ _assert("resolve_type_path 'a_mcard' succeeds", a_mcard_path is not None)
98
+ integer_path = resolve_type_path(clm_root, "integer")
99
+ _assert("resolve_type_path 'integer' succeeds", integer_path is not None)
100
+ agent_path = resolve_type_path(clm_root, "agent")
101
+ _assert("resolve_type_path 'agent' succeeds", agent_path is not None)
102
+
103
+ types_count = 0
104
+ for _root, _, files in os.walk(os.path.join(clm_root, "types")):
105
+ for file in files:
106
+ if file.endswith(".yaml"):
107
+ types_count += 1
108
+ _assert(f"Registry loaded 13+ types (got {types_count})", types_count >= 13)
109
+
110
+ print("\n-- 4. Universe Levels --")
111
+ def get_universe_level(clm_root, tname):
112
+ path = resolve_type_path(clm_root, tname)
113
+ if not path:
114
+ return None
115
+ with open(path, encoding="utf-8") as f:
116
+ data = yaml.safe_load(f)
117
+ return str(data.get("clm", {}).get("concrete_impl", {}).get("universe_level", "0"))
118
+
119
+ _assert("string is Level 0", get_universe_level(clm_root, "string") == "0")
120
+ _assert("integer is Level 0", get_universe_level(clm_root, "integer") == "0")
121
+ _assert("a_mcard is Level 1", get_universe_level(clm_root, "a_mcard") == "1")
122
+ _assert("b_mcard is Level 1", get_universe_level(clm_root, "b_mcard") == "1")
123
+ _assert("agent is Level 2", get_universe_level(clm_root, "agent") == "2")
124
+ _assert("clmEval is Level 2", get_universe_level(clm_root, "clmeval") == "2")
125
+
126
+ print("\n==================================================")
127
+ print(f" Results: {passed} passed, {failed} failed")
128
+ return 0 if failed == 0 else 1
129
+
130
+
131
+ def run_algebra_op(clm_root: str, op: str, *args: str) -> tuple[int, str, str]:
132
+ """
133
+ Runs a legacy shell modular algebra command and returns exit code and output.
134
+ """
135
+ import platform as _plat
136
+
137
+ from clm.layer0.utils import detect_host_os
138
+ host_os = detect_host_os()
139
+ arch = "amd64" if _plat.machine() in ("x86_64", "AMD64") else "arm64"
140
+ bash_cmd = f"""
141
+ export CLM_ROOT="{clm_root}"
142
+ export PATH="$CLM_ROOT/.venv/Scripts:$CLM_ROOT/.venv/bin:$CLM_ROOT/kernel/bin/{host_os}-{arch}:$CLM_ROOT/kernel/scripts:$PATH"
143
+ clm_root() {{ echo "$CLM_ROOT"; }}
144
+ export -f clm_root
145
+ source "$CLM_ROOT/computable_knowledge/Concrete/layer5_system/bootstrap/evaluator/shell_utils.sh" 2>/dev/null || true
146
+ source "$CLM_ROOT/computable_knowledge/Concrete/layer5_system/bootstrap/layer0_core/mcard_storage.sh" 2>/dev/null || true
147
+ source "$CLM_ROOT/computable_knowledge/Concrete/layer5_system/bootstrap/governance/register_handle.sh" 2>/dev/null || true
148
+ source "$CLM_ROOT/computable_knowledge/Concrete/layer5_system/bootstrap/layer0_core/clm_bootstrap.sh" 2>/dev/null || true
149
+ source "$CLM_ROOT/computable_knowledge/Concrete/layer5_system/bootstrap/governance/validate_grammar.sh" 2>/dev/null || true
150
+ source "$CLM_ROOT/computable_knowledge/Concrete/layer5_system/bootstrap/layer0_core/clm_algebra.sh" 2>/dev/null || true
151
+ source "$CLM_ROOT/computable_knowledge/Concrete/layer5_system/playbooks/diff_handle.sh" 2>/dev/null || true
152
+ {op} "$@"
153
+ """
154
+ proc = subprocess.Popen([get_bash_command(), "-c", bash_cmd, "--"] + list(args), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding="utf-8")
155
+ stdout_data, _ = proc.communicate()
156
+ return proc.returncode, stdout_data, ""
157
+
158
+
159
+ def test_baldwin_operators(clm_root: str) -> int:
160
+ """
161
+ Validates Baldwin modularity operators (split, port, augment) in the local database.
162
+ """
163
+ print("======================================================")
164
+ print(" Test Suite: Baldwin Modularity Operators (Python Native)")
165
+ print("======================================================\n")
166
+
167
+ passed = 0
168
+ failed = 0
169
+
170
+ def _assert(desc, cond):
171
+ nonlocal passed, failed
172
+ if cond:
173
+ print(f" ✅ {desc}")
174
+ passed += 1
175
+ return True
176
+ else:
177
+ print(f" ❌ {desc}")
178
+ failed += 1
179
+ return False
180
+
181
+ test_dir = os.path.join(clm_root, "data", "content_memory")
182
+ log_dir = os.path.join(clm_root, "data", "execution_logs")
183
+ scratch_dir = os.path.join(log_dir, ".baldwin_scratch")
184
+
185
+ os.makedirs(scratch_dir, exist_ok=True)
186
+ fixture_clm = os.path.join(scratch_dir, "fixture.yaml")
187
+
188
+ fixture_yaml = """clm:
189
+ abstract_spec:
190
+ context: "Baldwin test fixture"
191
+ goal: "A CLM fixture for testing"
192
+ success_criteria:
193
+ - "The CLM is structurally valid"
194
+ concrete_impl:
195
+ runtime: system
196
+ operation: test_baldwin_fixture
197
+ inputs:
198
+ - "test_input"
199
+ outputs:
200
+ - "record/test_output"
201
+ process:
202
+ type: shell
203
+ script: |
204
+ echo "hello from test_baldwin_fixture"
205
+ balanced_exp:
206
+ expectation: "The fixture CLM executes correctly"
207
+ pending_cases:
208
+ - given:
209
+ input: "test"
210
+ when:
211
+ operation: test_baldwin_fixture
212
+ then:
213
+ exit_code: 0
214
+ _meta:
215
+ clm_root_hash: sha256:0000000000000000000000000000000000000000000000000000000000000000
216
+ a_hash: sha256:0000000000000000000000000000000000000000000000000000000000000000
217
+ c_hash: sha256:0000000000000000000000000000000000000000000000000000000000000000
218
+ b_hash: sha256:0000000000000000000000000000000000000000000000000000000000000000
219
+ clm_name: test_fixture
220
+ computed_at: "2026-05-31T00:00:00Z"
221
+ """
222
+ with open(fixture_clm, "w", encoding="utf-8") as fh:
223
+ fh.write(fixture_yaml)
224
+
225
+ import sys
226
+ target = "clm.layer2.storage"
227
+ mod = sys.modules.get(target)
228
+ if mod is None:
229
+ __import__(target)
230
+ mod = sys.modules.get(target)
231
+ CLMDB = mod.CLMDB
232
+ register_handle = mod.register_handle
233
+
234
+ db = CLMDB(clm_root)
235
+ db.execute("content_memory", "DELETE FROM handle_history WHERE handle LIKE 'test:baldwin%';")
236
+ db.execute("content_memory", "DELETE FROM handle_registry WHERE handle LIKE 'test:baldwin%';")
237
+
238
+ # 1. SPLIT
239
+ print("-- 1. SPLIT (Decomposition) -------------------------")
240
+ rc, stdout, stderr = run_algebra_op(clm_root, "split", fixture_clm)
241
+ _assert("split returns 0", rc == 0)
242
+ _assert("split produces A-MCard", "A-MCard" in stdout)
243
+ _assert("split produces C-MCard", "C-MCard" in stdout)
244
+ _assert("split produces B-MCard", "B-MCard" in stdout)
245
+ _assert("split shows a_hash", "a_hash" in stdout)
246
+ _assert("split shows c_hash", "c_hash" in stdout)
247
+
248
+ a_files = [f for f in os.listdir(test_dir) if f.startswith("a_") and f.endswith(".yaml")]
249
+ c_files = [f for f in os.listdir(test_dir) if f.startswith("c_") and f.endswith(".yaml")]
250
+ b_files = [f for f in os.listdir(test_dir) if f.startswith("b_") and f.endswith(".yaml")]
251
+
252
+ _assert("A-MCard facet file created", len(a_files) > 0)
253
+ _assert("C-MCard facet file created", len(c_files) > 0)
254
+ _assert("B-MCard facet file created", len(b_files) > 0)
255
+
256
+ if a_files:
257
+ latest_a = sorted(a_files)[-1]
258
+ with open(os.path.join(test_dir, latest_a), encoding="utf-8") as f:
259
+ a_data = yaml.safe_load(f)
260
+ _assert("A-MCard facet is abstract_spec", "abstract_spec" in a_data.get("mcard", {}).get("facet", ""))
261
+
262
+ # 2. SUBSTITUTE
263
+ print("\n-- 2. SUBSTITUTE (Swap Implementation) --------------")
264
+ new_impl = os.path.join(scratch_dir, "new_impl.yaml")
265
+ new_impl_yaml = """runtime: system
266
+ operation: test_substituted_fixture
267
+ inputs:
268
+ - "new_input"
269
+ outputs:
270
+ - "record/new_output"
271
+ process:
272
+ type: shell
273
+ script: |
274
+ echo "substituted implementation"
275
+ """
276
+ with open(new_impl, "w", encoding="utf-8") as fh:
277
+ fh.write(new_impl_yaml)
278
+
279
+ rc, stdout, stderr = run_algebra_op(clm_root, "substitute", fixture_clm, new_impl)
280
+ _assert("substitute returns 0", rc == 0)
281
+
282
+ sub_file = None
283
+ for line in stdout.splitlines():
284
+ if "Substituted CLM:" in line:
285
+ sub_file = line.split("CLM:", 1)[1].strip()
286
+ break
287
+
288
+ if sub_file and os.path.exists(sub_file):
289
+ with open(sub_file, encoding="utf-8") as f:
290
+ sub_data = yaml.safe_load(f)
291
+ goal = sub_data.get("clm", {}).get("abstract_spec", {}).get("goal", "")
292
+ _assert("substitute preserves abstract_spec", "A CLM fixture for testing" in goal)
293
+ _assert("substitute retires tested_cases key", "tested_cases" not in sub_data.get("clm", {}).get("balanced_exp", {}))
294
+
295
+ # Verify grammar validation in-process via python
296
+ # Validate grammar by running compose-conditions or evaluate
297
+ from clm.layer0.algebra import load_normalized_manifest
298
+ try:
299
+ load_normalized_manifest(clm_root, sub_file)
300
+ _assert("substituted CLM passes grammar", True)
301
+ except Exception:
302
+ _assert("substituted CLM passes grammar", False)
303
+ else:
304
+ _assert("substitute produced output file", False)
305
+
306
+ # 3. AUGMENT
307
+ print("\n-- 3. AUGMENT (Add Layers + Handle History) ---------")
308
+ register_handle(clm_root, "test:baldwin_augment", fixture_clm)
309
+
310
+ res = db.execute("content_memory", "SELECT count(*) FROM handle_history WHERE handle = 'test:baldwin_augment';")
311
+ pre_history_count = int(res) if res else 0
312
+
313
+ aug_spec = os.path.join(scratch_dir, "aug_spec.yaml")
314
+ aug_spec_yaml = """pending_cases:
315
+ - given:
316
+ input: "augmented_test"
317
+ when:
318
+ operation: test_augmented
319
+ then:
320
+ exit_code: 0
321
+ """
322
+ with open(aug_spec, "w", encoding="utf-8") as fh:
323
+ fh.write(aug_spec_yaml)
324
+
325
+ rc, stdout, stderr = run_algebra_op(clm_root, "augment", fixture_clm, aug_spec)
326
+ _assert("augment returns 0", rc == 0)
327
+ _assert("augment reports pending cases added", "pending case" in stdout)
328
+
329
+ aug_file = None
330
+ for line in stdout.splitlines():
331
+ if "Augmented CLM:" in line:
332
+ aug_file = line.split("CLM:", 1)[1].strip()
333
+ break
334
+
335
+ if aug_file and os.path.exists(aug_file):
336
+ register_handle(clm_root, "test:baldwin_augment", aug_file)
337
+ else:
338
+ _assert("aug_file exists", False)
339
+
340
+ res = db.execute("content_memory", "SELECT count(*) FROM handle_history WHERE handle = 'test:baldwin_augment';")
341
+ post_history_count = int(res) if res else 0
342
+ _assert("handle_history entry created after augmentation", post_history_count > pre_history_count)
343
+
344
+ rc, stdout, stderr = run_algebra_op(clm_root, "diff_handle", "test:baldwin_augment")
345
+ _assert("diff_handle returns 0", rc == 0)
346
+ _assert("diff_handle shows handle name", "test:baldwin_augment" in stdout)
347
+
348
+ aug_sc = os.path.join(scratch_dir, "aug_sc.yaml")
349
+ with open(aug_sc, "w", encoding="utf-8") as fh:
350
+ fh.write('success_criteria: ["New criterion via augment"]\n')
351
+ rc, stdout, stderr = run_algebra_op(clm_root, "augment", fixture_clm, aug_sc)
352
+ _assert("augment adds success_criteria", "success criteria" in stdout)
353
+
354
+ # 4. EXCLUDE
355
+ print("\n-- 4. EXCLUDE (Prune + Audit + Handle History) ------")
356
+ rc, stdout, stderr = run_algebra_op(clm_root, "exclude", fixture_clm, ".clm.concrete_impl.inputs")
357
+ _assert("exclude non-essential field returns 0", rc == 0)
358
+ _assert("exclude reports archived content", "Archived" in stdout)
359
+
360
+ excl_file = None
361
+ audit_file = None
362
+ for line in stdout.splitlines():
363
+ if "Excluded CLM:" in line:
364
+ excl_file = line.split("CLM:", 1)[1].strip()
365
+ elif "Archived excluded content:" in line:
366
+ audit_file = line.split("content:", 1)[1].strip()
367
+
368
+ _assert("Exclude audit MCard created", audit_file is not None and os.path.exists(audit_file))
369
+ if audit_file and os.path.exists(audit_file):
370
+ with open(audit_file, encoding="utf-8") as f:
371
+ aud = yaml.safe_load(f)
372
+ _assert("Audit MCard records excluded path", aud.get("mcard", {}).get("excluded_path") == ".clm.concrete_impl.inputs")
373
+
374
+ if excl_file and os.path.exists(excl_file):
375
+ try:
376
+ load_normalized_manifest(clm_root, excl_file)
377
+ _assert("excluded CLM passes grammar validation", True)
378
+ except Exception:
379
+ _assert("excluded CLM passes grammar validation", False)
380
+
381
+ register_handle(clm_root, "test:baldwin_exclude", fixture_clm)
382
+ res = db.execute("content_memory", "SELECT count(*) FROM handle_history WHERE handle = 'test:baldwin_exclude';")
383
+ pre_excl_history = int(res) if res else 0
384
+
385
+ if excl_file and os.path.exists(excl_file):
386
+ register_handle(clm_root, "test:baldwin_exclude", excl_file)
387
+
388
+ res = db.execute("content_memory", "SELECT count(*) FROM handle_history WHERE handle = 'test:baldwin_exclude';")
389
+ post_excl_history = int(res) if res else 0
390
+ _assert("exclude creates handle_history entry for version tracking", post_excl_history > pre_excl_history)
391
+
392
+ prev_hash = db.execute("content_memory", "SELECT previous_hash FROM handle_history WHERE handle = 'test:baldwin_exclude' ORDER BY id DESC LIMIT 1;")
393
+ prev_hash = prev_hash.strip() if prev_hash else None
394
+ if prev_hash:
395
+ prev_content = db.execute("content_memory", f"SELECT content FROM card WHERE hash = '{prev_hash}';")
396
+ _assert("Previous version retrievable via handle_history", prev_content and "test_input" in prev_content)
397
+ else:
398
+ _assert("Previous version retrievable", False)
399
+
400
+ rc, stdout, stderr = run_algebra_op(clm_root, "exclude", fixture_clm, ".clm.abstract_spec")
401
+ _assert("exclude required field is rejected", rc != 0)
402
+
403
+ # 5. INVERT
404
+ print("\n-- 5. INVERT (Extract Rules) ------------------------")
405
+ rc, stdout, stderr = run_algebra_op(clm_root, "invert", fixture_clm, ".clm.concrete_impl.process.type", "promote")
406
+ _assert("invert promote returns 0", rc == 0)
407
+ _assert("invert reports promote to success_criteria", "success_criteria" in stdout)
408
+
409
+ inv_promote_file = None
410
+ for line in stdout.splitlines():
411
+ if "Inverted CLM:" in line:
412
+ inv_promote_file = line.split("CLM:", 1)[1].strip()
413
+ break
414
+
415
+ if inv_promote_file and os.path.exists(inv_promote_file):
416
+ with open(inv_promote_file, encoding="utf-8") as f:
417
+ inv_data = yaml.safe_load(f)
418
+ sc_len = len(inv_data.get("clm", {}).get("abstract_spec", {}).get("success_criteria", []))
419
+ _assert("Promoted CLM has additional success criteria", sc_len > 1)
420
+ else:
421
+ _assert("Invert promote file created", False)
422
+
423
+ rc, stdout, stderr = run_algebra_op(clm_root, "invert", fixture_clm, ".clm.concrete_impl.operation", "standalone")
424
+ _assert("invert standalone returns 0", rc == 0)
425
+
426
+ inv_standalone_file = None
427
+ for line in stdout.splitlines():
428
+ if "Inverted CLM:" in line:
429
+ inv_standalone_file = line.split("CLM:", 1)[1].strip()
430
+ break
431
+ elif "File:" in line:
432
+ inv_standalone_file = line.split("File:", 1)[1].strip()
433
+ break
434
+
435
+ if inv_standalone_file and os.path.exists(inv_standalone_file):
436
+ try:
437
+ load_normalized_manifest(clm_root, inv_standalone_file)
438
+ _assert("inverted standalone CLM passes grammar", True)
439
+ except Exception:
440
+ _assert("inverted standalone CLM passes grammar", False)
441
+ else:
442
+ _assert("Invert standalone file created", False)
443
+
444
+ rc, stdout, stderr = run_algebra_op(clm_root, "invert", fixture_clm, ".clm.nonexistent.path", "promote")
445
+ _assert("invert non-existent path returns 1", rc != 0)
446
+
447
+ # 6. PORT
448
+ print("\n-- 6. PORT (Migrate Environment) --------------------")
449
+ rc, stdout, stderr = run_algebra_op(clm_root, "port", fixture_clm, "python", "CPython 3.12 / Ubuntu 24.04 aarch64")
450
+ _assert("port returns 0", rc == 0)
451
+
452
+ port_file = None
453
+ port_audit = None
454
+ for line in stdout.splitlines():
455
+ if "Ported CLM:" in line:
456
+ port_file = line.split("CLM:", 1)[1].strip()
457
+ elif "Migration audit:" in line:
458
+ port_audit = line.split("audit:", 1)[1].strip()
459
+
460
+ if port_file and os.path.exists(port_file):
461
+ with open(port_file, encoding="utf-8") as f:
462
+ port_data = yaml.safe_load(f)
463
+ _assert("ported CLM has new runtime", port_data.get("clm", {}).get("concrete_impl", {}).get("runtime") == "python")
464
+ _assert("port retires tested_cases key", "tested_cases" not in port_data.get("clm", {}).get("balanced_exp", {}))
465
+ else:
466
+ _assert("port file created", False)
467
+
468
+ _assert("Port migration audit MCard created", port_audit is not None and os.path.exists(port_audit))
469
+ if port_audit and os.path.exists(port_audit):
470
+ with open(port_audit, encoding="utf-8") as f:
471
+ aud = yaml.safe_load(f)
472
+ _assert("Audit MCard records operation=port", aud.get("mcard", {}).get("operation") == "port")
473
+ _assert("Audit records new runtime", aud.get("mcard", {}).get("content", {}).get("new_runtime") == "python")
474
+
475
+ _assert("port reports evidence invalidated", "evidence invalidated" in stdout)
476
+
477
+ # 7. Handle History Verification
478
+ print("\n-- 7. Handle History (mcard_schema.sql Verification) -")
479
+ res = db.execute("content_memory", "SELECT count(*) FROM handle_history WHERE handle LIKE 'test:baldwin%';")
480
+ total_history = int(res) if res else 0
481
+ _assert("handle_history has ≥2 entries for test handles", total_history >= 2)
482
+
483
+ res = db.execute("content_memory", "SELECT count(*) FROM handle_registry WHERE handle LIKE 'test:baldwin%';")
484
+ total_handles = int(res) if res else 0
485
+ _assert("handle_registry has ≥2 test handles", total_handles >= 2)
486
+
487
+ res = db.execute("content_memory", "SELECT count(*) FROM handle_history hh INNER JOIN card c ON hh.previous_hash = c.hash WHERE hh.handle LIKE 'test:baldwin%';")
488
+ chain_valid = int(res) if res else 0
489
+ _assert("handle_history → card join resolves", chain_valid >= 1)
490
+
491
+ # Cleanup
492
+ shutil.rmtree(scratch_dir, ignore_errors=True)
493
+ db.execute("content_memory", "DELETE FROM handle_history WHERE handle LIKE 'test:baldwin%';")
494
+ db.execute("content_memory", "DELETE FROM handle_registry WHERE handle LIKE 'test:baldwin%';")
495
+
496
+ print("\n======================================================")
497
+ print(f" Results: {passed} passed, {failed} failed")
498
+ return 0 if failed == 0 else 1
@@ -0,0 +1,166 @@
1
+ """
2
+ Meta-Circular Type Inspector.
3
+
4
+ This module provides the built-in PCards (PCard_Pre, PCard_Post) required by the
5
+ Meta-Circular Evaluator to statically inspect Input and Output Types against
6
+ the generalized numbers defined in the architecture.
7
+
8
+ It utilizes a strictly data-driven registry of primitive types and ContentTypeInterpreter MIME types.
9
+ """
10
+
11
+ import json
12
+ from typing import Any
13
+
14
+ from clm.layer0.model.card import MCard
15
+ from clm.layer0.model.interpreter import ContentTypeInterpreter
16
+ from clm.layer0.model.pcard import PCard
17
+
18
+ PRIMITIVES = {
19
+ "string": str,
20
+ "int": int,
21
+ "double": float,
22
+ "float": float,
23
+ "date": str, # Parsing ISO strings or datetime objects
24
+ "object": dict,
25
+ "array": list,
26
+ "boolean": bool,
27
+ }
28
+
29
+
30
+ class TypeInspectorRegistry:
31
+ """Data-driven registry bridging primitives and content types."""
32
+
33
+ @classmethod
34
+ def get_supported_types(cls) -> set[str]:
35
+ interpreter = ContentTypeInterpreter()
36
+ mimes = set(interpreter._MIME_TO_EXTENSION.keys())
37
+ primitives = set(PRIMITIVES.keys())
38
+ return mimes.union(primitives)
39
+
40
+ @classmethod
41
+ def validate(cls, payload: Any, expected_type: str) -> bool:
42
+ if expected_type in PRIMITIVES:
43
+ # Special handling for primitive parsing if necessary
44
+ # For simplicity, we just check isinstance
45
+ return isinstance(payload, PRIMITIVES[expected_type])
46
+
47
+ # If it's a MIME type (content type fallback)
48
+ try:
49
+ # We strictly cast payload to str/bytes for detection if it's not
50
+ detect_payload = payload
51
+ if getattr(payload, "get_content", None):
52
+ detect_payload = payload.get_content(as_text=True)
53
+ elif not isinstance(payload, str | bytes):
54
+ detect_payload = json.dumps(payload)
55
+
56
+ interpreter = ContentTypeInterpreter()
57
+ detected_mime, _ = interpreter.detect_content_type(detect_payload)
58
+
59
+ # Application/json might actually just be valid for our custom MIME types natively
60
+ if detected_mime == expected_type:
61
+ return True
62
+
63
+ # Weak fallback: if expected is application/mcard or vcard, bypass strict detection
64
+ # if we confirm it's an MCard instance
65
+ if expected_type.startswith("application/mcard") and isinstance(
66
+ payload, MCard
67
+ ):
68
+ return True
69
+ if expected_type.startswith("application/vcard") and hasattr(
70
+ payload, "is_verification_vcard"
71
+ ):
72
+ return True
73
+
74
+ return detected_mime == expected_type
75
+ except Exception:
76
+ return False
77
+
78
+
79
+ def _pcard_validate(payload: Any, expected_type: str, phase: str) -> bool:
80
+ inspector = TypeInspectorRegistry()
81
+ if expected_type not in inspector.get_supported_types():
82
+ # Soft fallback for custom application types
83
+ if not expected_type.startswith("application/"):
84
+ raise ValueError(
85
+ f"Type '{expected_type}' is not a recognized static generalized number format."
86
+ )
87
+
88
+ if not inspector.validate(payload, expected_type):
89
+ raise TypeError(
90
+ f"Payload failed validation for type '{expected_type}' during {phase} phase."
91
+ )
92
+ return True
93
+
94
+
95
+ class TypeInspectorPCardPre:
96
+ """PCard implementation for validating inputs BEFORE execution."""
97
+
98
+ def execute(self, payload: Any, schema: list[dict[str, Any]]) -> PCard:
99
+ """
100
+ Takes the input payload and the expected schema geometry list.
101
+ Returns a v_pre PCard if successful.
102
+ """
103
+ from datetime import datetime, timezone
104
+
105
+ for field in schema:
106
+ field_name = field.get("name")
107
+ expected_type = field.get("type")
108
+
109
+ if isinstance(payload, dict):
110
+ field_val = payload.get(field_name)
111
+ else:
112
+ field_val = payload
113
+
114
+ _pcard_validate(field_val, expected_type, "Precondition")
115
+
116
+ m = MCard(json.dumps(payload) if isinstance(payload, dict) else str(payload))
117
+
118
+ content = {
119
+ "clm": {
120
+ "version": "1.0",
121
+ "type": "precondition-witness",
122
+ "timestamp": datetime.now(timezone.utc).isoformat(),
123
+ "target_hash": m.hash,
124
+ }
125
+ }
126
+ return PCard(json.dumps(content))
127
+
128
+
129
+ class TypeInspectorPCardPost:
130
+ """PCard implementation for validating outputs AFTER execution."""
131
+
132
+ def execute(
133
+ self, output: Any, schema: list[dict[str, Any]], pcard_hash: str
134
+ ) -> PCard:
135
+ """
136
+ Takes the execution output and expected output schema geometry.
137
+ Returns a v_post PCard if successful.
138
+ """
139
+ from datetime import datetime, timezone
140
+
141
+ for field in schema:
142
+ expected_type = field.get("type")
143
+
144
+ # Simple assumption: output is a single blob or dict matching schema keys
145
+ if isinstance(output, dict) and field.get("name") in output:
146
+ val = output.get(field.get("name"))
147
+ else:
148
+ val = output
149
+
150
+ _pcard_validate(val, expected_type, "Postcondition")
151
+
152
+ content = {
153
+ "clm": {
154
+ "version": "1.0",
155
+ "type": "postcondition-witness",
156
+ "pcard_hash": pcard_hash,
157
+ "timestamp": datetime.now(timezone.utc).isoformat(),
158
+ "output_repr": str(output)[:512],
159
+ }
160
+ }
161
+ return PCard(json.dumps(content))
162
+
163
+
164
+ # Singleton instances representing the autonomous PCards
165
+ PCard_Pre = TypeInspectorPCardPre()
166
+ PCard_Post = TypeInspectorPCardPost()