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.
- clm/__init__.py +230 -0
- clm/__main__.py +25 -0
- clm/cross_cutting/__init__.py +50 -0
- clm/cross_cutting/_test_runner.py +36 -0
- clm/cross_cutting/async_utils.py +25 -0
- clm/cross_cutting/cel_builder.py +123 -0
- clm/cross_cutting/cel_converter.py +697 -0
- clm/cross_cutting/cel_engine.py +252 -0
- clm/cross_cutting/cel_ops.py +72 -0
- clm/cross_cutting/cel_ops_db.py +157 -0
- clm/cross_cutting/cel_ops_files.py +99 -0
- clm/cross_cutting/cel_ops_state.py +71 -0
- clm/cross_cutting/cel_ops_strings.py +64 -0
- clm/cross_cutting/cel_resolver.py +63 -0
- clm/cross_cutting/cel_slices.py +56 -0
- clm/cross_cutting/cel_store.py +330 -0
- clm/cross_cutting/clm_logger.py +140 -0
- clm/cross_cutting/config/__init__.py +155 -0
- clm/cross_cutting/config/config_constants.py +392 -0
- clm/cross_cutting/config/env_parameters.py +90 -0
- clm/cross_cutting/config/logging.py +378 -0
- clm/cross_cutting/config/settings.py +504 -0
- clm/cross_cutting/context.py +5 -0
- clm/cross_cutting/domain_models.py +55 -0
- clm/cross_cutting/domain_types.py +61 -0
- clm/cross_cutting/effects.py +67 -0
- clm/cross_cutting/errors.py +153 -0
- clm/cross_cutting/governance.py +331 -0
- clm/cross_cutting/guards.py +41 -0
- clm/cross_cutting/mcard.py +321 -0
- clm/cross_cutting/native.py +185 -0
- clm/cross_cutting/observability.py +289 -0
- clm/cross_cutting/pcard.py +434 -0
- clm/cross_cutting/registry.py +71 -0
- clm/cross_cutting/resources.py +84 -0
- clm/cross_cutting/secrets.py +44 -0
- clm/cross_cutting/subprocess_utils.py +118 -0
- clm/cross_cutting/telemetry.py +164 -0
- clm/cross_cutting/testing/__init__.py +8 -0
- clm/cross_cutting/testing/comparator.py +187 -0
- clm/cross_cutting/testing/datasets.py +87 -0
- clm/cross_cutting/timeutil.py +20 -0
- clm/cross_cutting/types/new_type_check.py +0 -0
- clm/cross_cutting/utils/__init__.py +1 -0
- clm/cross_cutting/utils/url_safety.py +50 -0
- clm/cross_cutting/vcard.py +560 -0
- clm/cross_cutting/writer.py +118 -0
- clm/layer0/README.md +50 -0
- clm/layer0/__init__.py +223 -0
- clm/layer0/algebra.py +60 -0
- clm/layer0/algebra_baldwin.py +133 -0
- clm/layer0/algebra_baldwin_generators.py +36 -0
- clm/layer0/algebra_equivalence.py +262 -0
- clm/layer0/algebra_ingest.py +306 -0
- clm/layer0/algebra_manifest_io.py +156 -0
- clm/layer0/assembler.py +481 -0
- clm/layer0/cel/__init__.py +23 -0
- clm/layer0/cel_eval.py +491 -0
- clm/layer0/codec.py +106 -0
- clm/layer0/context.py +122 -0
- clm/layer0/db.py +160 -0
- clm/layer0/exceptions.py +73 -0
- clm/layer0/fibration.py +106 -0
- clm/layer0/gates.py +50 -0
- clm/layer0/hash.py +80 -0
- clm/layer0/loader.py +826 -0
- clm/layer0/math_utils.py +163 -0
- clm/layer0/mcard.py +96 -0
- clm/layer0/model/__init__.py +0 -0
- clm/layer0/model/action.py +223 -0
- clm/layer0/model/card.py +280 -0
- clm/layer0/model/card_triad.py +427 -0
- clm/layer0/model/compatibility.py +60 -0
- clm/layer0/model/dictionary.py +46 -0
- clm/layer0/model/dots.py +331 -0
- clm/layer0/model/event_producer.py +88 -0
- clm/layer0/model/g_time.py +89 -0
- clm/layer0/model/handle.py +163 -0
- clm/layer0/model/hash/__init__.py +6 -0
- clm/layer0/model/hash/algorithms/__init__.py +3 -0
- clm/layer0/model/hash/algorithms/custom_hash.py +7 -0
- clm/layer0/model/hash/algorithms/local_sha256.py +178 -0
- clm/layer0/model/hash/constants.py +53 -0
- clm/layer0/model/hash/enums.py +60 -0
- clm/layer0/model/hash/validator.py +307 -0
- clm/layer0/model/interpreter.py +275 -0
- clm/layer0/model/pagination.py +45 -0
- clm/layer0/model/pcard.py +716 -0
- clm/layer0/model/schema.py +44 -0
- clm/layer0/model/utils/__init__.py +1 -0
- clm/layer0/model/utils/content_analyzer.py +152 -0
- clm/layer0/model/validators/__init__.py +1 -0
- clm/layer0/model/validators/base_validator.py +44 -0
- clm/layer0/model/validators/binary_validator.py +66 -0
- clm/layer0/model/validators/text_validator.py +82 -0
- clm/layer0/model/validators/validation_registry.py +49 -0
- clm/layer0/model/vcard.py +823 -0
- clm/layer0/model/vcard_ext/__init__.py +39 -0
- clm/layer0/model/vcard_ext/core.py +60 -0
- clm/layer0/model/vcard_ext/network.py +23 -0
- clm/layer0/model/vcard_ext/observability.py +63 -0
- clm/layer0/model/vcard_ext/storage.py +60 -0
- clm/layer0/model/vcard_ext/vendors.py +211 -0
- clm/layer0/model/vcard_sandwich.py +119 -0
- clm/layer0/model/vcard_vocabulary.py +463 -0
- clm/layer0/model/workflow.py +274 -0
- clm/layer0/narrative.py +431 -0
- clm/layer0/ontology/collection.py +125 -0
- clm/layer0/parser.py +429 -0
- clm/layer0/relations.py +73 -0
- clm/layer0/rule_evaluator.py +251 -0
- clm/layer0/schema/__init__.py +38 -0
- clm/layer0/schema/ddl.py +97 -0
- clm/layer0/templates/abstract.yaml +99 -0
- clm/layer0/templates/balanced.yaml +253 -0
- clm/layer0/templates/concrete.yaml +172 -0
- clm/layer0/type_registry.py +223 -0
- clm/layer0/types.py +204 -0
- clm/layer0/utils.py +886 -0
- clm/layer0/verifier_core.py +262 -0
- clm/layer1/__init__.py +31 -0
- clm/layer1/action_dispatcher.py +275 -0
- clm/layer1/adapter_registry.py +233 -0
- clm/layer1/algebra_baldwin_generators.py +192 -0
- clm/layer1/arrow_compiler.py +525 -0
- clm/layer1/batch_processor.py +152 -0
- clm/layer1/cel/__init__.py +27 -0
- clm/layer1/cel/builder.py +173 -0
- clm/layer1/engine.py +759 -0
- clm/layer1/engine_async.py +89 -0
- clm/layer1/eval_callback.py +49 -0
- clm/layer1/gate_composer.py +229 -0
- clm/layer1/hoare_sandwich.py +298 -0
- clm/layer1/identity_guard.py +348 -0
- clm/layer1/matrix.py +138 -0
- clm/layer1/neural_runtime.py +221 -0
- clm/layer1/operations/__init__.py +123 -0
- clm/layer1/operations/augment.py +156 -0
- clm/layer1/operations/base.py +109 -0
- clm/layer1/operations/builtins.py +338 -0
- clm/layer1/operations/dispatch.py +144 -0
- clm/layer1/operations/exclude.py +107 -0
- clm/layer1/operations/handle.py +197 -0
- clm/layer1/operations/identity.py +139 -0
- clm/layer1/operations/invert.py +66 -0
- clm/layer1/operations/loader.py +116 -0
- clm/layer1/operations/manipulators/__init__.py +23 -0
- clm/layer1/operations/manipulators/document.py +211 -0
- clm/layer1/operations/manipulators/media.py +134 -0
- clm/layer1/operations/manipulators/structured.py +159 -0
- clm/layer1/operations/manipulators/tabular.py +334 -0
- clm/layer1/operations/port.py +65 -0
- clm/layer1/operations/services.py +529 -0
- clm/layer1/operations/split.py +117 -0
- clm/layer1/operations/substitute.py +75 -0
- clm/layer1/petri.py +1052 -0
- clm/layer1/pocketflow_orchestrator.py +408 -0
- clm/layer1/pocketflow_scheduler.py +519 -0
- clm/layer1/protocols.py +197 -0
- clm/layer1/runtime_adapter.py +718 -0
- clm/layer1/runtimes/__init__.py +71 -0
- clm/layer1/runtimes/_generated_assertions.py +125 -0
- clm/layer1/runtimes/_generated_types.py +42 -0
- clm/layer1/runtimes/base.py +265 -0
- clm/layer1/runtimes/binary.py +101 -0
- clm/layer1/runtimes/factory.py +203 -0
- clm/layer1/runtimes/javascript.py +321 -0
- clm/layer1/runtimes/javascript_runtime.js +33 -0
- clm/layer1/runtimes/js_scripts/isomorphism.mjs +22 -0
- clm/layer1/runtimes/js_scripts/loader.mjs +52 -0
- clm/layer1/runtimes/lambda_calc.py +126 -0
- clm/layer1/runtimes/python.py +288 -0
- clm/layer1/runtimes/python_runtime.py +41 -0
- clm/layer1/runtimes/script.py +114 -0
- clm/layer1/sandbox.py +334 -0
- clm/layer1/savepoint_guard.py +136 -0
- clm/layer1/sparse_net.py +122 -0
- clm/layer1/spec_tester.py +165 -0
- clm/layer1/store.py +295 -0
- clm/layer1/test_runner.py +498 -0
- clm/layer1/type_inspector.py +166 -0
- clm/layer1/verifier.py +772 -0
- clm/layer1/vm.py +91 -0
- clm/layer2/__init__.py +78 -0
- clm/layer2/card_collection.py +678 -0
- clm/layer2/classifier.py +479 -0
- clm/layer2/engine/__init__.py +1 -0
- clm/layer2/engine/abstract_sql_engine.py +320 -0
- clm/layer2/engine/base.py +193 -0
- clm/layer2/engine/duckdb_engine.py +576 -0
- clm/layer2/engine/sqlite_engine.py +518 -0
- clm/layer2/fiber/__init__.py +31 -0
- clm/layer2/fiber/context.py +89 -0
- clm/layer2/fiber/disposable.py +163 -0
- clm/layer2/fiber/fiber.py +125 -0
- clm/layer2/fiber/hoare.py +191 -0
- clm/layer2/file_io.py +376 -0
- clm/layer2/file_registrar.py +77 -0
- clm/layer2/ingest.py +202 -0
- clm/layer2/lineage.py +322 -0
- clm/layer2/mcard_fs.py +262 -0
- clm/layer2/merkle.py +11 -0
- clm/layer2/mime.py +244 -0
- clm/layer2/mime_detector.py +245 -0
- clm/layer2/private_collection.py +118 -0
- clm/layer2/shared_store.py +11 -0
- clm/layer2/storage/__init__.py +190 -0
- clm/layer2/storage/db_bitemporal.py +141 -0
- clm/layer2/storage/db_driver.py +331 -0
- clm/layer2/storage/db_hyperlinks.py +214 -0
- clm/layer2/storage/db_pool.py +139 -0
- clm/layer2/storage/db_repository.py +229 -0
- clm/layer2/storage/savepoint.py +78 -0
- clm/layer2/storage/sqlite_wal.py +74 -0
- clm/layer2/tridb.py +245 -0
- clm/layer2/vcard_receipt.py +71 -0
- clm/layer2/vfs.py +17 -0
- clm/layer3/__init__.py +141 -0
- clm/layer3/agency/__init__.py +19 -0
- clm/layer3/agency/config.py +220 -0
- clm/layer3/agency/providers/__init__.py +15 -0
- clm/layer3/agency/providers/base.py +91 -0
- clm/layer3/agency/providers/mlc_llm.py +169 -0
- clm/layer3/agency/providers/ollama.py +203 -0
- clm/layer3/agency/router.py +71 -0
- clm/layer3/agency/runtime.py +524 -0
- clm/layer3/gateway.py +353 -0
- clm/layer3/open_interpreter_adapter.py +159 -0
- clm/layer3/rag/__init__.py +70 -0
- clm/layer3/rag/cli.py +228 -0
- clm/layer3/rag/config.py +153 -0
- clm/layer3/rag/embeddings/__init__.py +16 -0
- clm/layer3/rag/embeddings/base.py +79 -0
- clm/layer3/rag/embeddings/ollama.py +211 -0
- clm/layer3/rag/embeddings/vision.py +290 -0
- clm/layer3/rag/engine.py +276 -0
- clm/layer3/rag/graph/__init__.py +22 -0
- clm/layer3/rag/graph/community.py +198 -0
- clm/layer3/rag/graph/engine.py +433 -0
- clm/layer3/rag/graph/extractor.py +255 -0
- clm/layer3/rag/graph/schema.py +115 -0
- clm/layer3/rag/graph/store.py +641 -0
- clm/layer3/rag/indexer.py +333 -0
- clm/layer3/rag/llm_providers.json +52 -0
- clm/layer3/rag/semantic_versioning.py +313 -0
- clm/layer3/rag/vector/__init__.py +28 -0
- clm/layer3/rag/vector/handle_vector_store.py +749 -0
- clm/layer3/rag/vector/schema.py +151 -0
- clm/layer3/rag/vector/store.py +632 -0
- clm/layer3/reticulum/__init__.py +55 -0
- clm/layer3/reticulum/bridge.py +74 -0
- clm/layer3/reticulum/daemon.py +88 -0
- clm/layer3/reticulum/discovery.py +164 -0
- clm/layer3/reticulum/identity.py +107 -0
- clm/layer3/reticulum/media.py +148 -0
- clm/layer3/reticulum/transport.py +133 -0
- clm/layer3/satori/__init__.py +209 -0
- clm/layer3/satori/alpha_conversion.py +168 -0
- clm/layer3/satori/beta_reduction.py +359 -0
- clm/layer3/satori/continuation.py +38 -0
- clm/layer3/satori/eta_conversion.py +205 -0
- clm/layer3/satori/free_variables.py +163 -0
- clm/layer3/satori/io_effects.py +370 -0
- clm/layer3/satori/lambda_runtime.py +726 -0
- clm/layer3/satori/lambda_term.py +230 -0
- clm/layer3/satori/sheaf_audit.py +261 -0
- clm/layer3/satori/speech_act.py +279 -0
- clm/layer4/README.md +9 -0
- clm/layer4/__init__.py +67 -0
- clm/layer4/_sovereign_executor.py +580 -0
- clm/layer4/action_commands.py +719 -0
- clm/layer4/api.py +236 -0
- clm/layer4/bootstrap/__init__.py +13 -0
- clm/layer4/bootstrap/bootstrapper.py +118 -0
- clm/layer4/bootstrap/cleanup.py +44 -0
- clm/layer4/bootstrap/clm_hooks.py +49 -0
- clm/layer4/bootstrap/genesis.py +77 -0
- clm/layer4/bootstrap/injection.py +125 -0
- clm/layer4/cli.py +549 -0
- clm/layer4/collection_manager.py +553 -0
- clm/layer4/commands/__init__.py +81 -0
- clm/layer4/commands/action_cmd.py +42 -0
- clm/layer4/commands/check_cmd.py +82 -0
- clm/layer4/commands/envelope.py +73 -0
- clm/layer4/commands/evaluate_cmd.py +224 -0
- clm/layer4/commands/mcard_cmd.py +24 -0
- clm/layer4/commands/petri_cmd.py +92 -0
- clm/layer4/commands/tridb_cmd.py +319 -0
- clm/layer4/commands/version_cmd.py +27 -0
- clm/layer4/diff_commands.py +167 -0
- clm/layer4/eoa_sponsor.py +232 -0
- clm/layer4/events.py +69 -0
- clm/layer4/flux_gateway.py +133 -0
- clm/layer4/gateway.py +91 -0
- clm/layer4/loader.py +307 -0
- clm/layer4/mcard_commands.py +166 -0
- clm/layer4/membrane.py +273 -0
- clm/layer4/navigation.py +50 -0
- clm/layer4/protocol/protocol_entry_python.py +108 -0
- clm/layer4/protocol/python_sync.py +126 -0
- clm/layer4/runner.py +150 -0
- clm/layer4/satori.py +262 -0
- clm/layer4/server/python_sync_client.py +150 -0
- clm/layer4/server/python_sync_server.py +139 -0
- clm/layer4/server/service_api.py +315 -0
- clm/layer4/server/start_servers.py +107 -0
- clm/layer4/server/stop_servers.py +24 -0
- clm/layer4/simulated_optimization_fix.py +0 -0
- clm/layer4/storage.py +463 -0
- clm/layer4/tridb_admin.py +268 -0
- clm/layer4/websocket/test_ws_client.py +104 -0
- clm/layer4/websocket/test_ws_server.py +138 -0
- clm/layer4/websocket/ws_server_local.py +160 -0
- clm/layer5/__init__.py +51 -0
- clm/layer5/async_batch_writer.py +133 -0
- clm/layer5/learning.py +276 -0
- clm/layer5/telemetry_hook.py +107 -0
- clm/layer5/type_lattice.py +238 -0
- clm/py.typed +0 -0
- clm/schemas/__init__.py +652 -0
- clm/schemas/abstract_face_schema.yaml +77 -0
- clm/schemas/cel_schema.yaml +416 -0
- clm/schemas/lifecycle/__init__.py +45 -0
- clm/schemas/lifecycle/models.py +123 -0
- clm/schemas/lifecycle/service.py +364 -0
- clm/schemas/mcard_schema.sql +192 -0
- clm/schemas/mcard_vector_schema.sql +283 -0
- clm/schemas/mlp-context-v1.json +91 -0
- clm_kernel-0.0.0.dist-info/METADATA +121 -0
- clm_kernel-0.0.0.dist-info/RECORD +333 -0
- clm_kernel-0.0.0.dist-info/WHEEL +4 -0
- clm_kernel-0.0.0.dist-info/entry_points.txt +3 -0
- 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()
|