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,251 @@
|
|
|
1
|
+
"""Hermetic Rule and Expression Evaluator (Sprint 394 / DEL-394-02).
|
|
2
|
+
|
|
3
|
+
Safe, sandboxed AST-based expression evaluator for Hoare pre- and post-condition invariants.
|
|
4
|
+
Supports CEL-like syntax, arithmetic, comparisons, logic, and bound MCard scope access.
|
|
5
|
+
Strict Zero-Host-Authority: Does NOT invoke Python eval() or exec().
|
|
6
|
+
|
|
7
|
+
Acceptance Criteria:
|
|
8
|
+
- AC-394-02-01: Evaluates expressions across boolean, numeric, string, collection attributes in <500µs.
|
|
9
|
+
- AC-394-02-02: Rejects arbitrary code execution, imports, or attributes outside bound scope.
|
|
10
|
+
- AC-394-02-03: Descriptive diagnostics pinpointing exact sub-expression evaluating to false.
|
|
11
|
+
|
|
12
|
+
Layer 0 module (zero dependencies on L1-L5).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import ast
|
|
18
|
+
import re
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RuleEvaluationError(Exception):
|
|
23
|
+
"""Raised when an expression cannot be safely parsed or evaluated."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ScopeWrapper:
|
|
27
|
+
"""Read-only wrapper providing dot-notation access to dictionaries and objects."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, data: Any) -> None:
|
|
30
|
+
self._data = data
|
|
31
|
+
|
|
32
|
+
def __getattr__(self, name: str) -> Any:
|
|
33
|
+
if isinstance(self._data, dict):
|
|
34
|
+
if name in self._data:
|
|
35
|
+
val = self._data[name]
|
|
36
|
+
return ScopeWrapper(val) if isinstance(val, (dict, list)) else val
|
|
37
|
+
raise AttributeError(f"Field '{name}' not found in scope")
|
|
38
|
+
if hasattr(self._data, name):
|
|
39
|
+
val = getattr(self._data, name)
|
|
40
|
+
return ScopeWrapper(val) if isinstance(val, (dict, list)) else val
|
|
41
|
+
raise AttributeError(f"Attribute '{name}' not found on object {type(self._data)}")
|
|
42
|
+
|
|
43
|
+
def __getitem__(self, item: Any) -> Any:
|
|
44
|
+
if isinstance(self._data, (dict, list)):
|
|
45
|
+
val = self._data[item]
|
|
46
|
+
return ScopeWrapper(val) if isinstance(val, (dict, list)) else val
|
|
47
|
+
raise KeyError(f"Cannot index non-collection: {type(self._data)}")
|
|
48
|
+
|
|
49
|
+
def __contains__(self, item: Any) -> bool:
|
|
50
|
+
if isinstance(self._data, (dict, list, set, str)):
|
|
51
|
+
return item in self._data
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
def __len__(self) -> int:
|
|
55
|
+
if hasattr(self._data, "__len__"):
|
|
56
|
+
return len(self._data)
|
|
57
|
+
return 0
|
|
58
|
+
|
|
59
|
+
def unwrap(self) -> Any:
|
|
60
|
+
return self._data
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class SafeRuleEvaluator:
|
|
64
|
+
"""Safe AST-based evaluator for CEL-style invariant expressions."""
|
|
65
|
+
|
|
66
|
+
ALLOWED_FUNCTIONS = {
|
|
67
|
+
"len": len,
|
|
68
|
+
"str": str,
|
|
69
|
+
"int": int,
|
|
70
|
+
"float": float,
|
|
71
|
+
"bool": bool,
|
|
72
|
+
"min": min,
|
|
73
|
+
"max": max,
|
|
74
|
+
"sum": sum,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def evaluate(cls, expression: str, context: dict[str, Any]) -> bool:
|
|
79
|
+
"""Evaluate a boolean expression against the given context dictionary."""
|
|
80
|
+
val = cls.eval_expr(expression, context)
|
|
81
|
+
return bool(val)
|
|
82
|
+
|
|
83
|
+
@classmethod
|
|
84
|
+
def eval_expr(cls, expression: str, context: dict[str, Any]) -> Any:
|
|
85
|
+
"""Evaluate an arbitrary safe arithmetic or boolean expression."""
|
|
86
|
+
clean_expr = cls._preprocess_syntax(expression)
|
|
87
|
+
try:
|
|
88
|
+
tree = ast.parse(clean_expr, mode="eval")
|
|
89
|
+
except SyntaxError as e:
|
|
90
|
+
raise RuleEvaluationError(f"Syntax error in expression '{expression}': {e}") from e
|
|
91
|
+
|
|
92
|
+
wrapped_ctx = {k: ScopeWrapper(v) if isinstance(v, (dict, list)) else v for k, v in context.items()}
|
|
93
|
+
return cls._eval_node(tree.body, wrapped_ctx)
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def _preprocess_syntax(cls, expr: str) -> str:
|
|
97
|
+
"""Normalize CEL/JS operators (&&, ||, !) into Python-compatible operators."""
|
|
98
|
+
res = expr.replace("&&", " and ").replace("||", " or ")
|
|
99
|
+
res = re.sub(r"!\s*(?!=)", "not ", res)
|
|
100
|
+
return res
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def _eval_node(cls, node: ast.AST, ctx: dict[str, Any]) -> Any:
|
|
104
|
+
"""Recursively evaluate an AST node within the hermetic sandbox."""
|
|
105
|
+
if isinstance(node, ast.Constant):
|
|
106
|
+
return node.value
|
|
107
|
+
|
|
108
|
+
if isinstance(node, ast.Name):
|
|
109
|
+
name = node.id
|
|
110
|
+
if name in ctx:
|
|
111
|
+
val = ctx[name]
|
|
112
|
+
return val.unwrap() if isinstance(val, ScopeWrapper) else val
|
|
113
|
+
if name in cls.ALLOWED_FUNCTIONS:
|
|
114
|
+
return cls.ALLOWED_FUNCTIONS[name]
|
|
115
|
+
if name in ("true", "True"):
|
|
116
|
+
return True
|
|
117
|
+
if name in ("false", "False"):
|
|
118
|
+
return False
|
|
119
|
+
if name in ("null", "None"):
|
|
120
|
+
return None
|
|
121
|
+
raise RuleEvaluationError(f"Undefined identifier in rule: '{name}'")
|
|
122
|
+
|
|
123
|
+
if isinstance(node, ast.Attribute):
|
|
124
|
+
val = cls._eval_node(node.value, ctx)
|
|
125
|
+
attr = node.attr
|
|
126
|
+
if isinstance(val, ScopeWrapper):
|
|
127
|
+
val = val.unwrap()
|
|
128
|
+
if isinstance(val, dict):
|
|
129
|
+
if attr in val:
|
|
130
|
+
return val[attr]
|
|
131
|
+
if attr == "contains":
|
|
132
|
+
return lambda item: item in val
|
|
133
|
+
raise RuleEvaluationError(f"Attribute '{attr}' not found in dict")
|
|
134
|
+
if attr == "contains" and isinstance(val, (list, tuple, set, str)):
|
|
135
|
+
return lambda item: item in val
|
|
136
|
+
if hasattr(val, attr):
|
|
137
|
+
attr_val = getattr(val, attr)
|
|
138
|
+
# Disallow dunder methods / internal attributes
|
|
139
|
+
if attr.startswith("_"):
|
|
140
|
+
raise RuleEvaluationError(f"Access to private attribute '{attr}' is forbidden")
|
|
141
|
+
return attr_val
|
|
142
|
+
raise RuleEvaluationError(f"Attribute '{attr}' does not exist on {type(val)}")
|
|
143
|
+
|
|
144
|
+
if isinstance(node, ast.Subscript):
|
|
145
|
+
val = cls._eval_node(node.value, ctx)
|
|
146
|
+
if isinstance(val, ScopeWrapper):
|
|
147
|
+
val = val.unwrap()
|
|
148
|
+
idx = cls._eval_node(node.slice, ctx)
|
|
149
|
+
try:
|
|
150
|
+
return val[idx]
|
|
151
|
+
except (KeyError, IndexError, TypeError) as e:
|
|
152
|
+
raise RuleEvaluationError(f"Subscript error: {e}") from e
|
|
153
|
+
|
|
154
|
+
if isinstance(node, ast.UnaryOp):
|
|
155
|
+
operand = cls._eval_node(node.operand, ctx)
|
|
156
|
+
if isinstance(node.op, ast.Not):
|
|
157
|
+
return not operand
|
|
158
|
+
if isinstance(node.op, ast.USub):
|
|
159
|
+
return -operand
|
|
160
|
+
if isinstance(node.op, ast.UAdd):
|
|
161
|
+
return +operand
|
|
162
|
+
raise RuleEvaluationError(f"Unsupported unary operator: {type(node.op)}")
|
|
163
|
+
|
|
164
|
+
if isinstance(node, ast.BinOp):
|
|
165
|
+
left = cls._eval_node(node.left, ctx)
|
|
166
|
+
right = cls._eval_node(node.right, ctx)
|
|
167
|
+
if isinstance(left, ScopeWrapper):
|
|
168
|
+
left = left.unwrap()
|
|
169
|
+
if isinstance(right, ScopeWrapper):
|
|
170
|
+
right = right.unwrap()
|
|
171
|
+
|
|
172
|
+
if isinstance(node.op, ast.Add):
|
|
173
|
+
return left + right
|
|
174
|
+
if isinstance(node.op, ast.Sub):
|
|
175
|
+
return left - right
|
|
176
|
+
if isinstance(node.op, ast.Mult):
|
|
177
|
+
return left * right
|
|
178
|
+
if isinstance(node.op, ast.Div):
|
|
179
|
+
return left / right
|
|
180
|
+
if isinstance(node.op, ast.FloorDiv):
|
|
181
|
+
return left // right
|
|
182
|
+
if isinstance(node.op, ast.Mod):
|
|
183
|
+
return left % right
|
|
184
|
+
raise RuleEvaluationError(f"Unsupported binary operator: {type(node.op)}")
|
|
185
|
+
|
|
186
|
+
if isinstance(node, ast.BoolOp):
|
|
187
|
+
if isinstance(node.op, ast.And):
|
|
188
|
+
for val_node in node.values:
|
|
189
|
+
if not cls._eval_node(val_node, ctx):
|
|
190
|
+
return False
|
|
191
|
+
return True
|
|
192
|
+
if isinstance(node.op, ast.Or):
|
|
193
|
+
for val_node in node.values:
|
|
194
|
+
if cls._eval_node(val_node, ctx):
|
|
195
|
+
return True
|
|
196
|
+
return False
|
|
197
|
+
raise RuleEvaluationError(f"Unsupported boolean operator: {type(node.op)}")
|
|
198
|
+
|
|
199
|
+
if isinstance(node, ast.Compare):
|
|
200
|
+
left = cls._eval_node(node.left, ctx)
|
|
201
|
+
if isinstance(left, ScopeWrapper):
|
|
202
|
+
left = left.unwrap()
|
|
203
|
+
for op, comparator in zip(node.ops, node.comparators):
|
|
204
|
+
right = cls._eval_node(comparator, ctx)
|
|
205
|
+
if isinstance(right, ScopeWrapper):
|
|
206
|
+
right = right.unwrap()
|
|
207
|
+
|
|
208
|
+
res = False
|
|
209
|
+
if isinstance(op, ast.Eq):
|
|
210
|
+
res = (left == right)
|
|
211
|
+
elif isinstance(op, ast.NotEq):
|
|
212
|
+
res = (left != right)
|
|
213
|
+
elif isinstance(op, ast.Lt):
|
|
214
|
+
res = (left < right)
|
|
215
|
+
elif isinstance(op, ast.LtE):
|
|
216
|
+
res = (left <= right)
|
|
217
|
+
elif isinstance(op, ast.Gt):
|
|
218
|
+
res = (left > right)
|
|
219
|
+
elif isinstance(op, ast.GtE):
|
|
220
|
+
res = (left >= right)
|
|
221
|
+
elif isinstance(op, ast.In):
|
|
222
|
+
res = (left in right)
|
|
223
|
+
elif isinstance(op, ast.NotIn):
|
|
224
|
+
res = (left not in right)
|
|
225
|
+
else:
|
|
226
|
+
raise RuleEvaluationError(f"Unsupported comparison operator: {type(op)}")
|
|
227
|
+
|
|
228
|
+
if not res:
|
|
229
|
+
return False
|
|
230
|
+
left = right
|
|
231
|
+
return True
|
|
232
|
+
|
|
233
|
+
if isinstance(node, ast.Call):
|
|
234
|
+
func = cls._eval_node(node.func, ctx)
|
|
235
|
+
args = [cls._eval_node(arg, ctx) for arg in node.args]
|
|
236
|
+
# Ensure safe method call
|
|
237
|
+
if callable(func):
|
|
238
|
+
return func(*args)
|
|
239
|
+
raise RuleEvaluationError(f"Object '{func}' is not callable")
|
|
240
|
+
|
|
241
|
+
if isinstance(node, ast.List):
|
|
242
|
+
return [cls._eval_node(elt, ctx) for elt in node.elts]
|
|
243
|
+
|
|
244
|
+
if isinstance(node, ast.Dict):
|
|
245
|
+
return {
|
|
246
|
+
cls._eval_node(k, ctx): cls._eval_node(v, ctx)
|
|
247
|
+
for k, v in zip(node.keys, node.values)
|
|
248
|
+
if k is not None
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
raise RuleEvaluationError(f"Disallowed AST expression element: {type(node).__name__}")
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Layer 0 Kenotic Schema Package (Sprint 387, DEL-387-02).
|
|
2
|
+
|
|
3
|
+
Pure static DDL definitions, table specifications, and Empty Schema constants (⊥)
|
|
4
|
+
free from database drivers or active filesystem side-effects.
|
|
5
|
+
"""
|
|
6
|
+
from clm.layer0.schema.ddl import (
|
|
7
|
+
CANONICAL_TRIAD_DDL,
|
|
8
|
+
CARD_TABLE_SPEC,
|
|
9
|
+
EMPTY_SCHEMA_VERSION,
|
|
10
|
+
HANDLE_HISTORY_SPEC,
|
|
11
|
+
HANDLE_REGISTRY_SPEC,
|
|
12
|
+
SQL_CREATE_CARD,
|
|
13
|
+
SQL_CREATE_HANDLE_HISTORY,
|
|
14
|
+
SQL_CREATE_HANDLE_REGISTRY,
|
|
15
|
+
SQL_CREATE_SCHEMA_VERSION,
|
|
16
|
+
TABLE_CARD,
|
|
17
|
+
TABLE_HANDLE_HISTORY,
|
|
18
|
+
TABLE_HANDLE_REGISTRY,
|
|
19
|
+
TABLE_SCHEMA_VERSION,
|
|
20
|
+
TableSpec,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"TableSpec",
|
|
25
|
+
"TABLE_CARD",
|
|
26
|
+
"TABLE_HANDLE_REGISTRY",
|
|
27
|
+
"TABLE_HANDLE_HISTORY",
|
|
28
|
+
"TABLE_SCHEMA_VERSION",
|
|
29
|
+
"EMPTY_SCHEMA_VERSION",
|
|
30
|
+
"CARD_TABLE_SPEC",
|
|
31
|
+
"HANDLE_REGISTRY_SPEC",
|
|
32
|
+
"HANDLE_HISTORY_SPEC",
|
|
33
|
+
"SQL_CREATE_CARD",
|
|
34
|
+
"SQL_CREATE_HANDLE_REGISTRY",
|
|
35
|
+
"SQL_CREATE_HANDLE_HISTORY",
|
|
36
|
+
"SQL_CREATE_SCHEMA_VERSION",
|
|
37
|
+
"CANONICAL_TRIAD_DDL",
|
|
38
|
+
]
|
clm/layer0/schema/ddl.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Static DDL schemas and Empty Schema (⊥) definitions (Sprint 387, INV-01).
|
|
2
|
+
|
|
3
|
+
Layer 0 Kenotic Purity: Schema definitions are pure static strings and table
|
|
4
|
+
specifications without physical database connections or active disk I/O.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Final, NamedTuple
|
|
9
|
+
|
|
10
|
+
# Canonical Table Names across the Sovereign Triad
|
|
11
|
+
TABLE_CARD: Final[str] = "card"
|
|
12
|
+
TABLE_HANDLE_REGISTRY: Final[str] = "handle_registry"
|
|
13
|
+
TABLE_HANDLE_HISTORY: Final[str] = "handle_history"
|
|
14
|
+
TABLE_SCHEMA_VERSION: Final[str] = "schema_version"
|
|
15
|
+
|
|
16
|
+
# Kenotic Empty Schema (⊥): The triad tables possess zero domain-specific columns.
|
|
17
|
+
# Domain semantics enter purely through content stored in MCards, never schema structure.
|
|
18
|
+
EMPTY_SCHEMA_VERSION: Final[str] = "3.0.3"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TableSpec(NamedTuple):
|
|
22
|
+
"""Declarative specification of an MCard triad table."""
|
|
23
|
+
name: str
|
|
24
|
+
columns: tuple[str, ...]
|
|
25
|
+
primary_key: tuple[str, ...]
|
|
26
|
+
description: str
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
CARD_TABLE_SPEC = TableSpec(
|
|
30
|
+
name=TABLE_CARD,
|
|
31
|
+
columns=("hash", "content", "g_time"),
|
|
32
|
+
primary_key=("hash",),
|
|
33
|
+
description="Content-Addressed Storage CAS table (Monad/Exponent).",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
HANDLE_REGISTRY_SPEC = TableSpec(
|
|
37
|
+
name=TABLE_HANDLE_REGISTRY,
|
|
38
|
+
columns=("handle", "current_hash", "created_at", "updated_at"),
|
|
39
|
+
primary_key=("handle",),
|
|
40
|
+
description="Semantic handle mapping mutable names to immutable CAS hashes (Sum/Appetition).",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
HANDLE_HISTORY_SPEC = TableSpec(
|
|
44
|
+
name=TABLE_HANDLE_HISTORY,
|
|
45
|
+
columns=("id", "handle", "previous_hash", "changed_at", "change_type"),
|
|
46
|
+
primary_key=("id",),
|
|
47
|
+
description="Append-only audit trail witnessing all handle transitions (η-conversion).",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Pure static DDL strings (executable by Layer 2 storage engines)
|
|
51
|
+
SQL_CREATE_CARD: Final[str] = """\
|
|
52
|
+
CREATE TABLE IF NOT EXISTS card (
|
|
53
|
+
hash TEXT PRIMARY KEY,
|
|
54
|
+
content BLOB NOT NULL,
|
|
55
|
+
g_time TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
56
|
+
);
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
SQL_CREATE_HANDLE_REGISTRY: Final[str] = """\
|
|
60
|
+
CREATE TABLE IF NOT EXISTS handle_registry (
|
|
61
|
+
handle TEXT PRIMARY KEY,
|
|
62
|
+
current_hash TEXT NOT NULL,
|
|
63
|
+
created_at TEXT NOT NULL,
|
|
64
|
+
updated_at TEXT NOT NULL,
|
|
65
|
+
FOREIGN KEY (current_hash) REFERENCES card(hash)
|
|
66
|
+
);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_handle_current_hash ON handle_registry(current_hash);
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
SQL_CREATE_HANDLE_HISTORY: Final[str] = """\
|
|
71
|
+
CREATE TABLE IF NOT EXISTS handle_history (
|
|
72
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
73
|
+
handle TEXT NOT NULL,
|
|
74
|
+
previous_hash TEXT NOT NULL,
|
|
75
|
+
changed_at TEXT NOT NULL,
|
|
76
|
+
change_type TEXT DEFAULT 'UPDATE',
|
|
77
|
+
FOREIGN KEY (handle) REFERENCES handle_registry(handle),
|
|
78
|
+
FOREIGN KEY (previous_hash) REFERENCES card(hash)
|
|
79
|
+
);
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_handle_history_handle ON handle_history(handle);
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
SQL_CREATE_SCHEMA_VERSION: Final[str] = """\
|
|
84
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
85
|
+
version TEXT PRIMARY KEY,
|
|
86
|
+
applied_at TEXT NOT NULL,
|
|
87
|
+
description TEXT
|
|
88
|
+
);
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
# Complete canonical DDL script for the empty schema (Kenosis ⊥)
|
|
92
|
+
CANONICAL_TRIAD_DDL: Final[str] = (
|
|
93
|
+
SQL_CREATE_CARD
|
|
94
|
+
+ SQL_CREATE_HANDLE_REGISTRY
|
|
95
|
+
+ SQL_CREATE_HANDLE_HISTORY
|
|
96
|
+
+ SQL_CREATE_SCHEMA_VERSION
|
|
97
|
+
)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Abstract Specification Template for CLM
|
|
2
|
+
# This template defines the WHAT dimension - the specification and intent
|
|
3
|
+
|
|
4
|
+
# Purpose and Intent
|
|
5
|
+
purpose: "Transform input data according to specified requirements" # Clear description of what this component does (min 10 characters)
|
|
6
|
+
|
|
7
|
+
# Input Specifications
|
|
8
|
+
inputs:
|
|
9
|
+
# Define expected inputs with types and constraints
|
|
10
|
+
# Example:
|
|
11
|
+
# data:
|
|
12
|
+
# type: "string"
|
|
13
|
+
# description: "Input data to process"
|
|
14
|
+
# constraints:
|
|
15
|
+
# min_length: 1
|
|
16
|
+
# max_length: 1000
|
|
17
|
+
|
|
18
|
+
# Output Specifications
|
|
19
|
+
outputs:
|
|
20
|
+
# Define expected outputs with types and constraints
|
|
21
|
+
# Example:
|
|
22
|
+
# result:
|
|
23
|
+
# type: "string"
|
|
24
|
+
# description: "Processed output data"
|
|
25
|
+
# constraints:
|
|
26
|
+
# min_length: 1
|
|
27
|
+
|
|
28
|
+
# Pre-conditions
|
|
29
|
+
preconditions:
|
|
30
|
+
# Conditions that must be true before execution
|
|
31
|
+
# Example:
|
|
32
|
+
# - "input data is valid UTF-8"
|
|
33
|
+
# - "system has sufficient memory"
|
|
34
|
+
# - "required permissions are granted"
|
|
35
|
+
|
|
36
|
+
# Post-conditions
|
|
37
|
+
postconditions:
|
|
38
|
+
# Conditions that must be true after execution
|
|
39
|
+
# Example:
|
|
40
|
+
# - "output is derived from input"
|
|
41
|
+
# - "system state remains consistent"
|
|
42
|
+
# - "no side effects beyond specified outputs"
|
|
43
|
+
|
|
44
|
+
# Success Criteria
|
|
45
|
+
success_criteria:
|
|
46
|
+
# Metrics for determining successful execution
|
|
47
|
+
# Example:
|
|
48
|
+
# functional:
|
|
49
|
+
# - "transformation preserves data integrity"
|
|
50
|
+
# performance:
|
|
51
|
+
# - "execution time < 100ms"
|
|
52
|
+
# quality:
|
|
53
|
+
# - "output meets specification requirements"
|
|
54
|
+
|
|
55
|
+
# Dependencies
|
|
56
|
+
dependencies:
|
|
57
|
+
# External dependencies and requirements
|
|
58
|
+
# Example:
|
|
59
|
+
# system:
|
|
60
|
+
# - "Python 3.9+"
|
|
61
|
+
# libraries:
|
|
62
|
+
# - "yaml"
|
|
63
|
+
# external:
|
|
64
|
+
# - "database connection"
|
|
65
|
+
|
|
66
|
+
# Constraints and Limitations
|
|
67
|
+
constraints:
|
|
68
|
+
# Known limitations and constraints
|
|
69
|
+
# Example:
|
|
70
|
+
# technical:
|
|
71
|
+
# - "maximum input size: 1MB"
|
|
72
|
+
# operational:
|
|
73
|
+
# - "requires internet connectivity"
|
|
74
|
+
# security:
|
|
75
|
+
# - "no access to filesystem"
|
|
76
|
+
|
|
77
|
+
# Version and Compatibility
|
|
78
|
+
version: "1.0.0"
|
|
79
|
+
compatibility:
|
|
80
|
+
min_version: "1.0.0"
|
|
81
|
+
max_version: "2.0.0"
|
|
82
|
+
|
|
83
|
+
# Tags and Classification
|
|
84
|
+
tags:
|
|
85
|
+
# Categorization for discovery and organization
|
|
86
|
+
# Example:
|
|
87
|
+
# - "data_processing"
|
|
88
|
+
# - "transformation"
|
|
89
|
+
# - "validation"
|
|
90
|
+
|
|
91
|
+
domain: "data_processing" # Application domain (e.g., "data_processing", "security", "ui")
|
|
92
|
+
|
|
93
|
+
# Documentation References
|
|
94
|
+
documentation:
|
|
95
|
+
# Links to additional documentation
|
|
96
|
+
# Example:
|
|
97
|
+
# specification: "link_to_spec"
|
|
98
|
+
# examples: "link_to_examples"
|
|
99
|
+
# tests: "link_to_tests"
|