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,504 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCard Unified Settings
|
|
3
|
+
======================
|
|
4
|
+
|
|
5
|
+
This module provides a single, unified interface for all MCard configuration.
|
|
6
|
+
It organizes settings into logical categories for better discoverability.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
from clm.cross_cutting.config.settings import settings
|
|
10
|
+
|
|
11
|
+
# Access database settings
|
|
12
|
+
db_path = settings.database.path
|
|
13
|
+
|
|
14
|
+
# Access API settings
|
|
15
|
+
port = settings.api.port
|
|
16
|
+
|
|
17
|
+
# Access hash settings
|
|
18
|
+
algorithm = settings.hashing.algorithm
|
|
19
|
+
|
|
20
|
+
# Access PTR runtime settings
|
|
21
|
+
timeout = settings.ptr.default_timeout
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import os
|
|
25
|
+
from dataclasses import dataclass, field
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Optional
|
|
28
|
+
|
|
29
|
+
import yaml
|
|
30
|
+
from dotenv import load_dotenv
|
|
31
|
+
|
|
32
|
+
from .config_constants import (
|
|
33
|
+
# Hashing
|
|
34
|
+
ALGORITHM_HIERARCHY,
|
|
35
|
+
API_KEY_HEADER_NAME,
|
|
36
|
+
CORS_ORIGINS,
|
|
37
|
+
DEFAULT_API_KEY,
|
|
38
|
+
# API
|
|
39
|
+
DEFAULT_API_PORT,
|
|
40
|
+
# Knowledge
|
|
41
|
+
DEFAULT_CONTENT_KNOWLEDGE_DIR,
|
|
42
|
+
# Database
|
|
43
|
+
DEFAULT_DB_PATH,
|
|
44
|
+
# Pool/Timeout
|
|
45
|
+
DEFAULT_HASH_ALGORITHM,
|
|
46
|
+
DEFAULT_HASH_CUSTOM_FUNCTION,
|
|
47
|
+
DEFAULT_HASH_CUSTOM_LENGTH,
|
|
48
|
+
DEFAULT_HASH_CUSTOM_MODULE,
|
|
49
|
+
# Identity Configuration
|
|
50
|
+
DEFAULT_IDENTITY_PROVIDER,
|
|
51
|
+
DEFAULT_IDENTITY_SPACE_PATH,
|
|
52
|
+
DEFAULT_LOG_LEVEL,
|
|
53
|
+
DEFAULT_LOG_PATH,
|
|
54
|
+
DEFAULT_MAX_FILE_SIZE,
|
|
55
|
+
DEFAULT_MAX_PROBLEM_TEXT_BYTES,
|
|
56
|
+
# Pagination
|
|
57
|
+
DEFAULT_PAGE_SIZE,
|
|
58
|
+
DEFAULT_POOL_SIZE,
|
|
59
|
+
DEFAULT_READ_TIMEOUT_SECS,
|
|
60
|
+
DEFAULT_TIMEOUT,
|
|
61
|
+
DEFAULT_WRAP_WIDTH_DEFAULT,
|
|
62
|
+
DEFAULT_WRAP_WIDTH_KNOWN,
|
|
63
|
+
ENV_API_KEY,
|
|
64
|
+
ENV_API_PORT,
|
|
65
|
+
ENV_CONTENT_KNOWLEDGE_DIR,
|
|
66
|
+
ENV_DB_MAX_CONNECTIONS,
|
|
67
|
+
# Environment Variable Names
|
|
68
|
+
ENV_DB_PATH,
|
|
69
|
+
ENV_DB_TIMEOUT,
|
|
70
|
+
ENV_DEFAULT_POOL_SIZE,
|
|
71
|
+
ENV_HASH_ALGORITHM,
|
|
72
|
+
ENV_HASH_CUSTOM_FUNCTION,
|
|
73
|
+
ENV_HASH_CUSTOM_LENGTH,
|
|
74
|
+
ENV_HASH_CUSTOM_MODULE,
|
|
75
|
+
ENV_IDENTITY_API_ENDPOINT,
|
|
76
|
+
ENV_IDENTITY_PROVIDER,
|
|
77
|
+
ENV_IDENTITY_SPACE_PATH,
|
|
78
|
+
ENV_KNOWLEDGE_VAULT,
|
|
79
|
+
ENV_MAX_FILE_SIZE,
|
|
80
|
+
ENV_MAX_PROBLEM_TEXT_BYTES,
|
|
81
|
+
ENV_READ_TIMEOUT_SECS,
|
|
82
|
+
ENV_SERVICE_LOG_LEVEL,
|
|
83
|
+
ENV_TEST_DB_PATH,
|
|
84
|
+
ENV_WRAP_WIDTH_DEFAULT,
|
|
85
|
+
ENV_WRAP_WIDTH_KNOWN,
|
|
86
|
+
HTTP_STATUS_FORBIDDEN,
|
|
87
|
+
HTTP_STATUS_INTERNAL_SERVER_ERROR,
|
|
88
|
+
HTTP_STATUS_NOT_FOUND,
|
|
89
|
+
# HTTP Status
|
|
90
|
+
HTTP_STATUS_OK,
|
|
91
|
+
# Logging
|
|
92
|
+
LOG_DIRECTORY,
|
|
93
|
+
LOG_FILENAME,
|
|
94
|
+
MAX_PAGE_SIZE,
|
|
95
|
+
MIN_PAGE_SIZE,
|
|
96
|
+
# PTR Timeouts
|
|
97
|
+
PTR_DEFAULT_TIMEOUT_SECS,
|
|
98
|
+
PTR_JULIA_TIMEOUT_SECS,
|
|
99
|
+
PTR_LEAN_TIMEOUT_SECS,
|
|
100
|
+
PTR_R_TIMEOUT_SECS,
|
|
101
|
+
SERVER_HOST,
|
|
102
|
+
TEST_DB_PATH,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _load_default_schema() -> dict:
|
|
107
|
+
"""Load the default database schema lazily to avoid import-time cycles."""
|
|
108
|
+
from clm.schemas import MCardSchema
|
|
109
|
+
|
|
110
|
+
schema = MCardSchema.get_instance()
|
|
111
|
+
return {
|
|
112
|
+
"documents": schema.get_table("mcard_fts"),
|
|
113
|
+
"card": schema.get_table("card"),
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
118
|
+
# Settings Data Classes
|
|
119
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@dataclass
|
|
123
|
+
class DatabaseSettings:
|
|
124
|
+
"""Database-related settings."""
|
|
125
|
+
|
|
126
|
+
path: str = DEFAULT_DB_PATH
|
|
127
|
+
test_path: str = TEST_DB_PATH
|
|
128
|
+
pool_size: int = DEFAULT_POOL_SIZE
|
|
129
|
+
timeout: float = DEFAULT_TIMEOUT
|
|
130
|
+
max_connections: int = DEFAULT_POOL_SIZE
|
|
131
|
+
schema: dict = field(default_factory=_load_default_schema)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass
|
|
135
|
+
class APISettings:
|
|
136
|
+
"""API server settings."""
|
|
137
|
+
|
|
138
|
+
port: int = DEFAULT_API_PORT
|
|
139
|
+
host: str = SERVER_HOST
|
|
140
|
+
api_key: str = DEFAULT_API_KEY
|
|
141
|
+
api_key_header: str = API_KEY_HEADER_NAME
|
|
142
|
+
cors_origins: list[str] = field(default_factory=lambda: CORS_ORIGINS.copy())
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass
|
|
146
|
+
class IdentitySettings:
|
|
147
|
+
"""Identity service and storage settings."""
|
|
148
|
+
|
|
149
|
+
provider: str = DEFAULT_IDENTITY_PROVIDER
|
|
150
|
+
space_path: str = DEFAULT_IDENTITY_SPACE_PATH
|
|
151
|
+
api_endpoint: str | None = None
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@dataclass
|
|
155
|
+
class PaginationSettings:
|
|
156
|
+
"""Pagination settings."""
|
|
157
|
+
|
|
158
|
+
default_page_size: int = DEFAULT_PAGE_SIZE
|
|
159
|
+
max_page_size: int = MAX_PAGE_SIZE
|
|
160
|
+
min_page_size: int = MIN_PAGE_SIZE
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@dataclass
|
|
164
|
+
class HashingSettings:
|
|
165
|
+
"""Hashing algorithm settings."""
|
|
166
|
+
|
|
167
|
+
algorithm: str = DEFAULT_HASH_ALGORITHM
|
|
168
|
+
custom_module: str = DEFAULT_HASH_CUSTOM_MODULE
|
|
169
|
+
custom_function: str = DEFAULT_HASH_CUSTOM_FUNCTION
|
|
170
|
+
custom_length: int = DEFAULT_HASH_CUSTOM_LENGTH
|
|
171
|
+
hierarchy: dict = field(default_factory=lambda: ALGORITHM_HIERARCHY.copy())
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@dataclass
|
|
175
|
+
class LoggingSettings:
|
|
176
|
+
"""Logging settings."""
|
|
177
|
+
|
|
178
|
+
directory: str = LOG_DIRECTORY
|
|
179
|
+
filename: str = LOG_FILENAME
|
|
180
|
+
default_path: str = DEFAULT_LOG_PATH
|
|
181
|
+
level: str = DEFAULT_LOG_LEVEL
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@dataclass
|
|
185
|
+
class FileProcessingSettings:
|
|
186
|
+
"""File processing settings."""
|
|
187
|
+
|
|
188
|
+
wrap_width_default: int = DEFAULT_WRAP_WIDTH_DEFAULT
|
|
189
|
+
wrap_width_known: int = DEFAULT_WRAP_WIDTH_KNOWN
|
|
190
|
+
max_problem_text_bytes: int = DEFAULT_MAX_PROBLEM_TEXT_BYTES
|
|
191
|
+
read_timeout_secs: float = DEFAULT_READ_TIMEOUT_SECS
|
|
192
|
+
max_file_size: int = DEFAULT_MAX_FILE_SIZE
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@dataclass
|
|
196
|
+
class BootstrapSettings:
|
|
197
|
+
"""Bootstrap procedure schema configurations."""
|
|
198
|
+
|
|
199
|
+
db_dir: str = "db"
|
|
200
|
+
manifests_dir: str = "../clm/bootstrap_phases"
|
|
201
|
+
identity_db_name: str = "agent_identities.db"
|
|
202
|
+
content_db_name: str = "content_memory.db"
|
|
203
|
+
log_db_name: str = "execution_log.db"
|
|
204
|
+
genesis_manifest: str = "00a_phase_a_genesis_identity.yaml"
|
|
205
|
+
cleanup_manifest: str = "cleanup_procedure.yaml"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@dataclass
|
|
209
|
+
class KnowledgeSettings:
|
|
210
|
+
"""Content knowledge source directory configuration."""
|
|
211
|
+
|
|
212
|
+
content_knowledge_dir: str = DEFAULT_CONTENT_KNOWLEDGE_DIR
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@dataclass
|
|
216
|
+
class PTRSettings:
|
|
217
|
+
"""Polynomial Type Runtime settings."""
|
|
218
|
+
|
|
219
|
+
# Subprocess timeouts
|
|
220
|
+
default_timeout: int = PTR_DEFAULT_TIMEOUT_SECS
|
|
221
|
+
lean_timeout: int = PTR_LEAN_TIMEOUT_SECS
|
|
222
|
+
julia_timeout: int = PTR_JULIA_TIMEOUT_SECS
|
|
223
|
+
r_timeout: int = PTR_R_TIMEOUT_SECS
|
|
224
|
+
|
|
225
|
+
# Allowed imports for sandboxed Python
|
|
226
|
+
allowed_imports: dict[str, str] = field(default_factory=dict)
|
|
227
|
+
|
|
228
|
+
# Safe builtins for sandbox
|
|
229
|
+
safe_builtins: set[str] = field(default_factory=set)
|
|
230
|
+
|
|
231
|
+
# Runtime command configurations (migrating away from this in Phase 2)
|
|
232
|
+
runtime_config: dict = field(default_factory=dict)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@dataclass
|
|
236
|
+
class HTTPStatus:
|
|
237
|
+
"""HTTP status code constants."""
|
|
238
|
+
|
|
239
|
+
OK: int = HTTP_STATUS_OK
|
|
240
|
+
FORBIDDEN: int = HTTP_STATUS_FORBIDDEN
|
|
241
|
+
NOT_FOUND: int = HTTP_STATUS_NOT_FOUND
|
|
242
|
+
INTERNAL_SERVER_ERROR: int = HTTP_STATUS_INTERNAL_SERVER_ERROR
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
246
|
+
# Main Settings Class
|
|
247
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class Settings:
|
|
251
|
+
"""
|
|
252
|
+
Unified settings container for MCard.
|
|
253
|
+
|
|
254
|
+
Provides organized access to all configuration through category-specific
|
|
255
|
+
properties.
|
|
256
|
+
|
|
257
|
+
This is a singleton - use `settings` instance instead of creating new ones.
|
|
258
|
+
"""
|
|
259
|
+
|
|
260
|
+
_instance: Optional["Settings"] = None
|
|
261
|
+
_initialized: bool = False
|
|
262
|
+
|
|
263
|
+
def __new__(cls) -> "Settings":
|
|
264
|
+
if cls._instance is None:
|
|
265
|
+
cls._instance = super().__new__(cls)
|
|
266
|
+
return cls._instance
|
|
267
|
+
|
|
268
|
+
def __init__(self):
|
|
269
|
+
if Settings._initialized:
|
|
270
|
+
return
|
|
271
|
+
|
|
272
|
+
# Load environment variables
|
|
273
|
+
load_dotenv()
|
|
274
|
+
|
|
275
|
+
# Load system configuration yaml
|
|
276
|
+
self._yaml_config = self._load_system_config_yaml()
|
|
277
|
+
|
|
278
|
+
# Initialize category settings
|
|
279
|
+
self._database = self._init_database_settings()
|
|
280
|
+
self._identity = self._init_identity_settings()
|
|
281
|
+
self._api = self._init_api_settings()
|
|
282
|
+
self._bootstrap = BootstrapSettings()
|
|
283
|
+
self._knowledge = self._init_knowledge_settings()
|
|
284
|
+
self._pagination = PaginationSettings()
|
|
285
|
+
self._hashing = self._init_hashing_settings()
|
|
286
|
+
self._logging = self._init_logging_settings()
|
|
287
|
+
self._file_processing = self._init_file_processing_settings()
|
|
288
|
+
self._ptr = self._init_ptr_settings()
|
|
289
|
+
self._http_status = HTTPStatus()
|
|
290
|
+
|
|
291
|
+
Settings._initialized = True
|
|
292
|
+
|
|
293
|
+
def _load_system_config_yaml(self) -> dict:
|
|
294
|
+
"""Load external settings from mcard_system_config.yaml."""
|
|
295
|
+
candidates = [
|
|
296
|
+
Path(__file__).parent.parent.parent / "schema" / "mcard_system_config.yaml",
|
|
297
|
+
Path.cwd() / "schema" / "mcard_system_config.yaml",
|
|
298
|
+
]
|
|
299
|
+
for path in candidates:
|
|
300
|
+
if path.exists():
|
|
301
|
+
try:
|
|
302
|
+
with open(path, encoding="utf-8") as f:
|
|
303
|
+
data = yaml.safe_load(f)
|
|
304
|
+
return data.get("settings", {})
|
|
305
|
+
except Exception:
|
|
306
|
+
pass
|
|
307
|
+
return {}
|
|
308
|
+
|
|
309
|
+
def _init_database_settings(self) -> DatabaseSettings:
|
|
310
|
+
"""Initialize database settings from environment and yaml."""
|
|
311
|
+
return DatabaseSettings(
|
|
312
|
+
path=os.getenv(ENV_DB_PATH, DEFAULT_DB_PATH),
|
|
313
|
+
test_path=os.getenv(ENV_TEST_DB_PATH, TEST_DB_PATH),
|
|
314
|
+
pool_size=int(os.getenv(ENV_DEFAULT_POOL_SIZE, DEFAULT_POOL_SIZE)),
|
|
315
|
+
timeout=float(os.getenv(ENV_DB_TIMEOUT, DEFAULT_TIMEOUT)),
|
|
316
|
+
max_connections=int(os.getenv(ENV_DB_MAX_CONNECTIONS, DEFAULT_POOL_SIZE)),
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
def _init_ptr_settings(self) -> PTRSettings:
|
|
320
|
+
"""Initialize PTR settings from loaded schema config."""
|
|
321
|
+
s_conf = self._yaml_config.get("sandbox", {})
|
|
322
|
+
t_conf = self._yaml_config.get("timeouts", {})
|
|
323
|
+
|
|
324
|
+
# We start migrating away from runtime_config inside python,
|
|
325
|
+
# but keep an empty dict if someone is holding on to it
|
|
326
|
+
r_conf = self._yaml_config.get("runtime_config", {})
|
|
327
|
+
|
|
328
|
+
return PTRSettings(
|
|
329
|
+
default_timeout=t_conf.get("default_runtime", PTR_DEFAULT_TIMEOUT_SECS),
|
|
330
|
+
lean_timeout=t_conf.get("lean_runtime", PTR_LEAN_TIMEOUT_SECS),
|
|
331
|
+
julia_timeout=t_conf.get("julia_runtime", PTR_JULIA_TIMEOUT_SECS),
|
|
332
|
+
r_timeout=t_conf.get("r_runtime", PTR_R_TIMEOUT_SECS),
|
|
333
|
+
allowed_imports=s_conf.get("allowed_imports", {}),
|
|
334
|
+
safe_builtins=set(s_conf.get("safe_builtins", [])),
|
|
335
|
+
runtime_config=r_conf,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
def _init_identity_settings(self) -> IdentitySettings:
|
|
339
|
+
"""Initialize identity settings from environment."""
|
|
340
|
+
return IdentitySettings(
|
|
341
|
+
provider=os.getenv(ENV_IDENTITY_PROVIDER, DEFAULT_IDENTITY_PROVIDER),
|
|
342
|
+
space_path=os.getenv(ENV_IDENTITY_SPACE_PATH, DEFAULT_IDENTITY_SPACE_PATH),
|
|
343
|
+
api_endpoint=os.getenv(ENV_IDENTITY_API_ENDPOINT),
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
def _init_api_settings(self) -> APISettings:
|
|
347
|
+
"""Initialize API settings from environment."""
|
|
348
|
+
return APISettings(
|
|
349
|
+
port=int(os.getenv(ENV_API_PORT, DEFAULT_API_PORT)),
|
|
350
|
+
api_key=os.getenv(ENV_API_KEY, DEFAULT_API_KEY),
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
def _init_knowledge_settings(self) -> KnowledgeSettings:
|
|
354
|
+
"""Initialize content knowledge settings from environment and config."""
|
|
355
|
+
val = os.getenv(ENV_KNOWLEDGE_VAULT) or os.getenv(
|
|
356
|
+
ENV_CONTENT_KNOWLEDGE_DIR,
|
|
357
|
+
DEFAULT_CONTENT_KNOWLEDGE_DIR,
|
|
358
|
+
)
|
|
359
|
+
if val:
|
|
360
|
+
val = str(Path(val).expanduser().resolve())
|
|
361
|
+
return KnowledgeSettings(content_knowledge_dir=val)
|
|
362
|
+
|
|
363
|
+
def _init_hashing_settings(self) -> HashingSettings:
|
|
364
|
+
"""Initialize hashing settings from environment."""
|
|
365
|
+
env_algo = None
|
|
366
|
+
if os.getenv("CLM_HASH_CONFIG"):
|
|
367
|
+
env_algo = os.getenv("CLM_HASH_CONFIG").split("|")[0].strip().lower()
|
|
368
|
+
elif os.getenv("CLM_HASH_ALGO"):
|
|
369
|
+
env_algo = os.getenv("CLM_HASH_ALGO").strip().lower()
|
|
370
|
+
elif os.getenv(ENV_HASH_ALGORITHM):
|
|
371
|
+
env_algo = os.getenv(ENV_HASH_ALGORITHM).strip().lower()
|
|
372
|
+
|
|
373
|
+
if not env_algo:
|
|
374
|
+
env_algo = DEFAULT_HASH_ALGORITHM
|
|
375
|
+
|
|
376
|
+
return HashingSettings(
|
|
377
|
+
algorithm=env_algo,
|
|
378
|
+
custom_module=os.getenv(ENV_HASH_CUSTOM_MODULE, DEFAULT_HASH_CUSTOM_MODULE),
|
|
379
|
+
custom_function=os.getenv(
|
|
380
|
+
ENV_HASH_CUSTOM_FUNCTION, DEFAULT_HASH_CUSTOM_FUNCTION
|
|
381
|
+
),
|
|
382
|
+
custom_length=int(
|
|
383
|
+
os.getenv(ENV_HASH_CUSTOM_LENGTH, DEFAULT_HASH_CUSTOM_LENGTH)
|
|
384
|
+
),
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
def _init_logging_settings(self) -> LoggingSettings:
|
|
388
|
+
"""Initialize logging settings from environment."""
|
|
389
|
+
return LoggingSettings(
|
|
390
|
+
level=os.getenv(ENV_SERVICE_LOG_LEVEL, DEFAULT_LOG_LEVEL),
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
def _init_file_processing_settings(self) -> FileProcessingSettings:
|
|
394
|
+
"""Initialize file processing settings from environment."""
|
|
395
|
+
return FileProcessingSettings(
|
|
396
|
+
wrap_width_default=int(
|
|
397
|
+
os.getenv(ENV_WRAP_WIDTH_DEFAULT, DEFAULT_WRAP_WIDTH_DEFAULT)
|
|
398
|
+
),
|
|
399
|
+
wrap_width_known=int(
|
|
400
|
+
os.getenv(ENV_WRAP_WIDTH_KNOWN, DEFAULT_WRAP_WIDTH_KNOWN)
|
|
401
|
+
),
|
|
402
|
+
max_problem_text_bytes=int(
|
|
403
|
+
os.getenv(ENV_MAX_PROBLEM_TEXT_BYTES, DEFAULT_MAX_PROBLEM_TEXT_BYTES)
|
|
404
|
+
),
|
|
405
|
+
read_timeout_secs=float(
|
|
406
|
+
os.getenv(ENV_READ_TIMEOUT_SECS, DEFAULT_READ_TIMEOUT_SECS)
|
|
407
|
+
),
|
|
408
|
+
max_file_size=int(os.getenv(ENV_MAX_FILE_SIZE, DEFAULT_MAX_FILE_SIZE)),
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
412
|
+
# Properties
|
|
413
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
414
|
+
|
|
415
|
+
@property
|
|
416
|
+
def database(self) -> DatabaseSettings:
|
|
417
|
+
"""Database configuration."""
|
|
418
|
+
return self._database
|
|
419
|
+
|
|
420
|
+
@property
|
|
421
|
+
def identity(self) -> IdentitySettings:
|
|
422
|
+
"""Identity space configuration."""
|
|
423
|
+
return self._identity
|
|
424
|
+
|
|
425
|
+
@property
|
|
426
|
+
def api(self) -> APISettings:
|
|
427
|
+
"""API server configuration."""
|
|
428
|
+
return self._api
|
|
429
|
+
|
|
430
|
+
@property
|
|
431
|
+
def bootstrap(self) -> BootstrapSettings:
|
|
432
|
+
"""Bootstrap database logic configuration."""
|
|
433
|
+
return self._bootstrap
|
|
434
|
+
|
|
435
|
+
@property
|
|
436
|
+
def knowledge(self) -> KnowledgeSettings:
|
|
437
|
+
"""Content knowledge source configuration."""
|
|
438
|
+
return self._knowledge
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def pagination(self) -> PaginationSettings:
|
|
442
|
+
"""Pagination configuration."""
|
|
443
|
+
return self._pagination
|
|
444
|
+
|
|
445
|
+
@property
|
|
446
|
+
def hashing(self) -> HashingSettings:
|
|
447
|
+
"""Hashing algorithm configuration."""
|
|
448
|
+
return self._hashing
|
|
449
|
+
|
|
450
|
+
@property
|
|
451
|
+
def logging(self) -> LoggingSettings:
|
|
452
|
+
"""Logging configuration."""
|
|
453
|
+
return self._logging
|
|
454
|
+
|
|
455
|
+
@property
|
|
456
|
+
def file_processing(self) -> FileProcessingSettings:
|
|
457
|
+
"""File processing configuration."""
|
|
458
|
+
return self._file_processing
|
|
459
|
+
|
|
460
|
+
@property
|
|
461
|
+
def ptr(self) -> PTRSettings:
|
|
462
|
+
"""Polynomial Type Runtime configuration."""
|
|
463
|
+
return self._ptr
|
|
464
|
+
|
|
465
|
+
@property
|
|
466
|
+
def http_status(self) -> HTTPStatus:
|
|
467
|
+
"""HTTP status code constants."""
|
|
468
|
+
return self._http_status
|
|
469
|
+
|
|
470
|
+
def reload(self) -> None:
|
|
471
|
+
"""Reload settings from environment (for testing)."""
|
|
472
|
+
Settings._initialized = False
|
|
473
|
+
self.__init__()
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
477
|
+
# Singleton Instance
|
|
478
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
479
|
+
|
|
480
|
+
# The canonical settings instance
|
|
481
|
+
settings = Settings()
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
485
|
+
# Module Exports
|
|
486
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
487
|
+
|
|
488
|
+
__all__ = [
|
|
489
|
+
# Main settings object
|
|
490
|
+
"settings",
|
|
491
|
+
"Settings",
|
|
492
|
+
# Category classes (for type hints)
|
|
493
|
+
"DatabaseSettings",
|
|
494
|
+
"IdentitySettings",
|
|
495
|
+
"APISettings",
|
|
496
|
+
"BootstrapSettings",
|
|
497
|
+
"KnowledgeSettings",
|
|
498
|
+
"PaginationSettings",
|
|
499
|
+
"HashingSettings",
|
|
500
|
+
"LoggingSettings",
|
|
501
|
+
"FileProcessingSettings",
|
|
502
|
+
"PTRSettings",
|
|
503
|
+
"HTTPStatus",
|
|
504
|
+
]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Pydantic v2 Domain Models for CLM Mathematical Entities (Sprint 176 / Sprint 384).
|
|
2
|
+
|
|
3
|
+
Canonical definitions have been relocated to clm.layer0.model.card_triad (DEL-384-01).
|
|
4
|
+
This module provides backward-compatible re-exports for all legacy callers (DEL-384-02).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from clm.layer0.model.card_triad import (
|
|
10
|
+
AgentDid,
|
|
11
|
+
BailVerdict,
|
|
12
|
+
BooleanPCard,
|
|
13
|
+
CardModel,
|
|
14
|
+
ContentHash,
|
|
15
|
+
CordisCoeffects,
|
|
16
|
+
DynamicPCard,
|
|
17
|
+
InvariantPhase,
|
|
18
|
+
MarkingModel,
|
|
19
|
+
MCard,
|
|
20
|
+
PCard,
|
|
21
|
+
PCardDefinition,
|
|
22
|
+
PlaceId,
|
|
23
|
+
PlaceModel,
|
|
24
|
+
PrimitivePCard,
|
|
25
|
+
TokenModel,
|
|
26
|
+
TransitionId,
|
|
27
|
+
TransitionModel,
|
|
28
|
+
VCard,
|
|
29
|
+
compute_canonical_hash,
|
|
30
|
+
compute_canonical_serialized,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"AgentDid",
|
|
35
|
+
"BailVerdict",
|
|
36
|
+
"BooleanPCard",
|
|
37
|
+
"CardModel",
|
|
38
|
+
"ContentHash",
|
|
39
|
+
"CordisCoeffects",
|
|
40
|
+
"DynamicPCard",
|
|
41
|
+
"InvariantPhase",
|
|
42
|
+
"MarkingModel",
|
|
43
|
+
"MCard",
|
|
44
|
+
"PCard",
|
|
45
|
+
"PCardDefinition",
|
|
46
|
+
"PlaceId",
|
|
47
|
+
"PlaceModel",
|
|
48
|
+
"PrimitivePCard",
|
|
49
|
+
"TokenModel",
|
|
50
|
+
"TransitionId",
|
|
51
|
+
"TransitionModel",
|
|
52
|
+
"VCard",
|
|
53
|
+
"compute_canonical_hash",
|
|
54
|
+
"compute_canonical_serialized",
|
|
55
|
+
]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Domain NewTypes and invariant constructors for CLM (Sprint 176).
|
|
2
|
+
|
|
3
|
+
Defines strongly-typed wrappers for primitive identifiers to prevent cross-assignment errors
|
|
4
|
+
at static analysis time and runtime.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
from typing import NewType
|
|
11
|
+
|
|
12
|
+
# Content-addressed hash (raw 64-char hex or algorithm-prefixed e.g. blake3:..., sha256:...)
|
|
13
|
+
ContentHash = NewType("ContentHash", str)
|
|
14
|
+
|
|
15
|
+
# W3C Decentralized Identifier (e.g. did:key:z6Mku..., did:pkc:ca:...)
|
|
16
|
+
AgentDid = NewType("AgentDid", str)
|
|
17
|
+
|
|
18
|
+
# Semantic handle identifier (e.g. mcard:kernel:schema, pcard:eval:split)
|
|
19
|
+
HandleName = NewType("HandleName", str)
|
|
20
|
+
|
|
21
|
+
# Petri Net topology identifiers
|
|
22
|
+
PlaceId = NewType("PlaceId", str)
|
|
23
|
+
TransitionId = NewType("TransitionId", str)
|
|
24
|
+
MarkingHash = NewType("MarkingHash", str)
|
|
25
|
+
|
|
26
|
+
_HASH_REGEX = re.compile(r"^(?:(blake3|sha256):)?[a-fA-F0-9]{8,64}$")
|
|
27
|
+
_DID_REGEX = re.compile(r"^did:[a-zA-Z0-9_-]+:.+$")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def make_content_hash(val: str) -> ContentHash:
|
|
31
|
+
"""Validate and wrap a content-addressed hash string.
|
|
32
|
+
|
|
33
|
+
Raises ValueError if string is empty or does not match hex/algorithm-prefixed hash format.
|
|
34
|
+
"""
|
|
35
|
+
clean = val.strip()
|
|
36
|
+
if not clean:
|
|
37
|
+
raise ValueError("ContentHash cannot be empty")
|
|
38
|
+
if not _HASH_REGEX.match(clean):
|
|
39
|
+
# Allow existing legacy formats if non-empty, but enforce non-empty
|
|
40
|
+
if len(clean) < 4:
|
|
41
|
+
raise ValueError(f"Invalid ContentHash format: '{val}'")
|
|
42
|
+
return ContentHash(clean)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def make_agent_did(val: str) -> AgentDid:
|
|
46
|
+
"""Validate and wrap a W3C DID string.
|
|
47
|
+
|
|
48
|
+
Raises ValueError if string does not start with 'did:'.
|
|
49
|
+
"""
|
|
50
|
+
clean = val.strip()
|
|
51
|
+
if not clean.startswith("did:") or len(clean) < 5:
|
|
52
|
+
raise ValueError(f"Invalid DID format: '{val}' (must start with 'did:')")
|
|
53
|
+
return AgentDid(clean)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def make_handle_name(val: str) -> HandleName:
|
|
57
|
+
"""Validate and wrap a semantic handle string."""
|
|
58
|
+
clean = val.strip()
|
|
59
|
+
if not clean:
|
|
60
|
+
raise ValueError("HandleName cannot be empty")
|
|
61
|
+
return HandleName(clean)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""EffectRegistry — side-effect isolation (Thunk pattern).
|
|
2
|
+
|
|
3
|
+
Extracted from ``cel_store.py`` in Sprint 132.1. The Thunk pattern is a
|
|
4
|
+
peer of the State monad (CelStore), not a sibling helper bolted onto it.
|
|
5
|
+
|
|
6
|
+
Side effects (env vars, file I/O, subprocess) are registered here and
|
|
7
|
+
dispatched through the store, not called directly by op handlers.
|
|
8
|
+
This makes them mockable, loggable, and auditable.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class EffectRegistry:
|
|
18
|
+
"""Registry for side-effect handlers (Thunk pattern)."""
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
self._effects: dict[str, Callable] = {}
|
|
22
|
+
|
|
23
|
+
def register(self, name: str, handler: Callable) -> None:
|
|
24
|
+
self._effects[name] = handler
|
|
25
|
+
|
|
26
|
+
def execute(self, name: str, *args: Any, **kwargs: Any) -> Any:
|
|
27
|
+
handler = self._effects.get(name)
|
|
28
|
+
if handler is None:
|
|
29
|
+
raise ValueError(f"Unknown effect: {name}")
|
|
30
|
+
return handler(*args, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def register_default_effects(effects_registry: EffectRegistry) -> None:
|
|
34
|
+
"""Register default side-effect handlers into an EffectRegistry."""
|
|
35
|
+
import os as _os
|
|
36
|
+
import shutil as _shutil
|
|
37
|
+
|
|
38
|
+
def _write_file_effect(filepath: str, content: str) -> bool:
|
|
39
|
+
try:
|
|
40
|
+
_os.makedirs(_os.path.dirname(filepath), exist_ok=True)
|
|
41
|
+
with open(filepath, "w", encoding="utf-8") as fw:
|
|
42
|
+
fw.write(content)
|
|
43
|
+
return True
|
|
44
|
+
except Exception:
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
def _run_test_suite_effect(test_path: str, clm_root: str, env: dict | None = None, timeout: int = 300) -> int:
|
|
48
|
+
import subprocess
|
|
49
|
+
|
|
50
|
+
from clm.cross_cutting._test_runner import build_test_command
|
|
51
|
+
cmd_env = _os.environ.copy()
|
|
52
|
+
if env:
|
|
53
|
+
cmd_env.update({k: str(v) for k, v in env.items()})
|
|
54
|
+
cmd = build_test_command(test_path, clm_root)
|
|
55
|
+
proc = subprocess.Popen(cmd, env=cmd_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
56
|
+
try:
|
|
57
|
+
proc.communicate(timeout=timeout)
|
|
58
|
+
except subprocess.TimeoutExpired:
|
|
59
|
+
proc.kill()
|
|
60
|
+
proc.communicate()
|
|
61
|
+
return proc.returncode
|
|
62
|
+
|
|
63
|
+
effects_registry.register("set_env", lambda var, val: _os.environ.__setitem__(var, val))
|
|
64
|
+
effects_registry.register("unset_env", lambda var: _os.environ.pop(var, None))
|
|
65
|
+
effects_registry.register("write_file", _write_file_effect)
|
|
66
|
+
effects_registry.register("run_test_suite", _run_test_suite_effect)
|
|
67
|
+
effects_registry.register("copy_file", lambda src, dest: _shutil.copy(src, dest))
|