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,321 @@
|
|
|
1
|
+
"""Cross-Cutting — MCard (Σ-type / Data Plane / Carrier)
|
|
2
|
+
|
|
3
|
+
MCard is the root type / Dependent Sum (Σ-type) of the MVP Cards triad.
|
|
4
|
+
It is the irreducible, content-addressed, immutable unit of data.
|
|
5
|
+
Every other card (PCard, VCard) is ultimately stored *as* an MCard
|
|
6
|
+
(the Empty Schema Principle).
|
|
7
|
+
|
|
8
|
+
Design references:
|
|
9
|
+
- MVP Cards Design Rationale (§MCard — Data Plane)
|
|
10
|
+
- The Empty Schema Principle
|
|
11
|
+
- Function-Number Duality
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import time
|
|
16
|
+
from typing import Any, Literal
|
|
17
|
+
|
|
18
|
+
from pydantic import BaseModel, Field
|
|
19
|
+
|
|
20
|
+
from clm.cross_cutting.telemetry import jsonl_emit_typed
|
|
21
|
+
from clm.cross_cutting.timeutil import default_agent_did as _default_agent_did
|
|
22
|
+
from clm.cross_cutting.timeutil import now_g_time as _now_g_time
|
|
23
|
+
from clm.layer0.context import CLMContext
|
|
24
|
+
from clm.layer0.utils import clm_hash_string as hash_string
|
|
25
|
+
from clm.layer0.utils import prefixed_hash_raw
|
|
26
|
+
|
|
27
|
+
# Unified Card Model (Sprint 131.1)
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
_TOKEN_WRAPPER = {
|
|
31
|
+
"mcard": "mcard",
|
|
32
|
+
"state": "state_token",
|
|
33
|
+
"pcard": "pcard_token",
|
|
34
|
+
"vcard": "vcard_token",
|
|
35
|
+
}
|
|
36
|
+
_WRAPPER_TO_TOKEN = {v: k for k, v in _TOKEN_WRAPPER.items()}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Card(BaseModel):
|
|
40
|
+
"""The unified Monadic Card primitive (Sprint 131).
|
|
41
|
+
|
|
42
|
+
CLM is the single meta-language; this is its one object. ``token_type``
|
|
43
|
+
selects both the MLTT role and the YAML wrapper key emitted by
|
|
44
|
+
:meth:`to_yaml`, preserving byte-parity with the four legacy manual
|
|
45
|
+
formatters (``make_mcard_content``, ``emit_state_token``,
|
|
46
|
+
``serialize_pcard``, ``vcard_gate``):
|
|
47
|
+
|
|
48
|
+
mcard -> mcard: (Σ-type / Noun Phrase / data plane)
|
|
49
|
+
state -> state_token: (Σ-subtype / PCard output snapshot)
|
|
50
|
+
pcard -> pcard_token: (Π-type / Verb Phrase / control plane)
|
|
51
|
+
vcard -> vcard_token: (Id-type / Sentence / verification witness)
|
|
52
|
+
"""
|
|
53
|
+
token_type: Literal["mcard", "state", "pcard", "vcard"] = "mcard"
|
|
54
|
+
g_time: str = Field(default_factory=_now_g_time)
|
|
55
|
+
agent_did: str = Field(default_factory=_default_agent_did)
|
|
56
|
+
timestamp: str | None = None
|
|
57
|
+
operation: str | None = None
|
|
58
|
+
|
|
59
|
+
# mcard (data) payload
|
|
60
|
+
content_hash: str | None = None
|
|
61
|
+
content: str | None = None
|
|
62
|
+
source: dict[str, str] | None = None
|
|
63
|
+
runtime_facts: Any | None = None
|
|
64
|
+
|
|
65
|
+
# state (PCard output) payload
|
|
66
|
+
producer_pcard_hash: str | None = None
|
|
67
|
+
vcard_dispatch_hash: str | None = None
|
|
68
|
+
content_snapshot: str | None = None
|
|
69
|
+
|
|
70
|
+
# pcard (control) payload
|
|
71
|
+
runtime: str | None = None
|
|
72
|
+
script_hash: str | None = None
|
|
73
|
+
input_place_hashes: list[str] = Field(default_factory=list)
|
|
74
|
+
pcard_hash: str | None = None
|
|
75
|
+
|
|
76
|
+
# vcard (witness) payload
|
|
77
|
+
gate_type: Literal["callback", "dispatch"] | None = None
|
|
78
|
+
result: Literal["pass", "fail"] | None = None
|
|
79
|
+
sponsor_did: str | None = None
|
|
80
|
+
delegation_proof: str | None = None
|
|
81
|
+
execution_locale_hash: str | None = None
|
|
82
|
+
transport_ref: str | None = None
|
|
83
|
+
failure_reason: str | None = None
|
|
84
|
+
triggering_dispatch_hash: str | None = None
|
|
85
|
+
downstream_callback_targets: list[str] | None = None
|
|
86
|
+
|
|
87
|
+
# Sprint 132.5: cached hash (manual _hash_cache instead of frozen=True +
|
|
88
|
+
# cached_property, to avoid breaking list[str]/Any fields per spec §9.4).
|
|
89
|
+
_hash_cache: str | None = None
|
|
90
|
+
|
|
91
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
92
|
+
if name != "_hash_cache" and hasattr(self, "_hash_cache"):
|
|
93
|
+
object.__setattr__(self, "_hash_cache", None)
|
|
94
|
+
super().__setattr__(name, value)
|
|
95
|
+
|
|
96
|
+
# -- serialization ------------------------------------------------
|
|
97
|
+
|
|
98
|
+
def _q(self, v: Any) -> str:
|
|
99
|
+
"""Quote a scalar the way the legacy formatters do (always double-quoted)."""
|
|
100
|
+
s = str(v).replace("\\", "\\\\").replace('"', '\\"')
|
|
101
|
+
return f'"{s}"'
|
|
102
|
+
|
|
103
|
+
def _yaml_list(self, key: str, items: list[str] | None, indent: str = " ") -> str:
|
|
104
|
+
"""Render a list field exactly like the legacy formatters."""
|
|
105
|
+
if not items:
|
|
106
|
+
return f"{indent}{key}: []"
|
|
107
|
+
out = f"{indent}{key}:\n"
|
|
108
|
+
for h in items:
|
|
109
|
+
out += f'{indent} - {self._q(h)}\n'
|
|
110
|
+
return out.rstrip("\n")
|
|
111
|
+
|
|
112
|
+
def to_yaml(self) -> str:
|
|
113
|
+
"""Canonical YAML with the wrapper key preserved.
|
|
114
|
+
|
|
115
|
+
Byte-parity target for the four legacy formatters. Each token_type
|
|
116
|
+
emits only the fields its legacy counterpart emits, in the same
|
|
117
|
+
order, with the same double-quoting and 4-space list indentation.
|
|
118
|
+
"""
|
|
119
|
+
tt = self.token_type
|
|
120
|
+
if tt == "mcard":
|
|
121
|
+
src = self.source or {}
|
|
122
|
+
parts = ["mcard:"]
|
|
123
|
+
parts.append(f' g_time: {self._q(self.g_time)}')
|
|
124
|
+
if self.content_hash is not None:
|
|
125
|
+
parts.append(f' content_hash: {self._q(self.content_hash)}')
|
|
126
|
+
if src:
|
|
127
|
+
parts.append(" source:")
|
|
128
|
+
for k in ("filename", "mime_type", "encoding"):
|
|
129
|
+
if k in src:
|
|
130
|
+
parts.append(f' {k}: {self._q(src[k])}')
|
|
131
|
+
if self.content is not None:
|
|
132
|
+
parts.append(f' content: {self._q(self.content)}')
|
|
133
|
+
return "\n".join(parts) + "\n"
|
|
134
|
+
|
|
135
|
+
if tt == "pcard":
|
|
136
|
+
parts = ["pcard_token:"]
|
|
137
|
+
parts.append(f' operation: {self._q(self.operation or "")}')
|
|
138
|
+
parts.append(f' runtime: {self._q(self.runtime or "")}')
|
|
139
|
+
parts.append(f' script_hash: {self._q(self.script_hash or "")}')
|
|
140
|
+
parts.append(f' timestamp: {self._q(self.timestamp or "")}')
|
|
141
|
+
parts.append(self._yaml_list("input_place_hashes", self.input_place_hashes))
|
|
142
|
+
return "\n".join(parts)
|
|
143
|
+
|
|
144
|
+
if tt == "state":
|
|
145
|
+
parts = ["state_token:"]
|
|
146
|
+
parts.append(f' token_type: {self._q("state")}')
|
|
147
|
+
parts.append(f' producer_pcard_hash: {self._q(self.producer_pcard_hash or "")}')
|
|
148
|
+
parts.append(f' vcard_dispatch_hash: {self._q(self.vcard_dispatch_hash or "")}')
|
|
149
|
+
parts.append(f' timestamp: {self._q(self.timestamp or "")}')
|
|
150
|
+
parts.append(f' agent_did: {self._q(self.agent_did)}')
|
|
151
|
+
parts.append(f' content_snapshot: {self._q(self.content_snapshot or "")}')
|
|
152
|
+
return "\n".join(parts)
|
|
153
|
+
|
|
154
|
+
if tt == "vcard":
|
|
155
|
+
parts = ["vcard_token:"]
|
|
156
|
+
parts.append(f' gate_type: {self._q(self.gate_type or "")}')
|
|
157
|
+
parts.append(f' result: {self._q(self.result or "")}')
|
|
158
|
+
parts.append(f' pcard_hash: {self._q(self.pcard_hash or "")}')
|
|
159
|
+
if self.gate_type == "callback":
|
|
160
|
+
parts.append(f' triggering_dispatch_hash: {self._q(self.triggering_dispatch_hash or "")}')
|
|
161
|
+
parts.append(f' timestamp: {self._q(self.timestamp or "")}')
|
|
162
|
+
parts.append(f' agent_did: {self._q(self.agent_did)}')
|
|
163
|
+
parts.append(f' sponsor_did: {self._q(self.sponsor_did or "")}')
|
|
164
|
+
parts.append(f' delegation_proof: {self._q(self.delegation_proof or "")}')
|
|
165
|
+
parts.append(f' execution_locale_hash: {self._q(self.execution_locale_hash or "")}')
|
|
166
|
+
parts.append(f' transport_ref: {self._q(self.transport_ref or "")}')
|
|
167
|
+
if self.failure_reason is not None:
|
|
168
|
+
parts.append(f' failure_reason: {self._q(self.failure_reason)}')
|
|
169
|
+
if self.gate_type == "callback":
|
|
170
|
+
# callback mode omits input_place_hashes entirely when empty
|
|
171
|
+
# (matches legacy formatter); only renders when non-empty
|
|
172
|
+
if self.input_place_hashes:
|
|
173
|
+
parts.append(self._yaml_list("input_place_hashes", self.input_place_hashes))
|
|
174
|
+
else:
|
|
175
|
+
parts.append(self._yaml_list("downstream_callback_targets", self.downstream_callback_targets))
|
|
176
|
+
return "\n".join(parts)
|
|
177
|
+
|
|
178
|
+
raise ValueError(f"Unknown token_type: {tt}")
|
|
179
|
+
|
|
180
|
+
@classmethod
|
|
181
|
+
def from_yaml(cls, yaml_str: str) -> "Card":
|
|
182
|
+
"""Parse a Card from its wrapper-key YAML representation."""
|
|
183
|
+
import yaml
|
|
184
|
+
data = yaml.safe_load(yaml_str)
|
|
185
|
+
if isinstance(data, dict) and len(data) == 1:
|
|
186
|
+
wrapper, payload = next(iter(data.items()))
|
|
187
|
+
token_type = _WRAPPER_TO_TOKEN.get(wrapper, "mcard")
|
|
188
|
+
if isinstance(payload, dict):
|
|
189
|
+
return cls(**{**payload, "token_type": token_type})
|
|
190
|
+
raise ValueError(f"Unrecognized card YAML: {yaml_str[:80]!r}")
|
|
191
|
+
|
|
192
|
+
def compute_hash(self) -> str:
|
|
193
|
+
"""SHA-256 of the canonical YAML (deterministic, cached).
|
|
194
|
+
|
|
195
|
+
Sprint 132.5: result is cached via ``_hash_cache`` and invalidated
|
|
196
|
+
on any field mutation via ``__setattr__``.
|
|
197
|
+
"""
|
|
198
|
+
if self._hash_cache is None:
|
|
199
|
+
object.__setattr__(self, "_hash_cache", hash_string(self.to_yaml()))
|
|
200
|
+
return self._hash_cache
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# ---------------------------------------------------------------------------
|
|
204
|
+
# Sprint 384 (DEL-384-02): Re-export canonical MCard from Layer 0 card_triad
|
|
205
|
+
from clm.layer0.model.card_triad import MCard # noqa: F401
|
|
206
|
+
|
|
207
|
+
# ---------------------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
def emit_state_token(
|
|
210
|
+
ctx: CLMContext,
|
|
211
|
+
pcard_hash: str,
|
|
212
|
+
vcard_dispatch_hash: str,
|
|
213
|
+
content_input: str,
|
|
214
|
+
) -> str:
|
|
215
|
+
"""Emit a state token MCard and persist it to the execution log.
|
|
216
|
+
|
|
217
|
+
A state token captures the output of a PCard execution as a new
|
|
218
|
+
MCard, maintaining the algebraic closure invariant:
|
|
219
|
+
PCard(MCard) → MCard'.
|
|
220
|
+
|
|
221
|
+
Sprint 131.5: YAML emission now delegates to ``Card(token_type="state", ...).to_yaml()``
|
|
222
|
+
so the unified model is the single source of truth; the ``save_card_and_handle``,
|
|
223
|
+
``jsonl_emit``, and on-disk log side effects are preserved.
|
|
224
|
+
"""
|
|
225
|
+
timestamp = _now_g_time()
|
|
226
|
+
agent_did = _default_agent_did()
|
|
227
|
+
|
|
228
|
+
if os.path.exists(content_input):
|
|
229
|
+
file_size = os.path.getsize(content_input)
|
|
230
|
+
if file_size > 4096:
|
|
231
|
+
with open(content_input, "rb") as f:
|
|
232
|
+
h = hash_string(f.read())
|
|
233
|
+
content_snapshot = prefixed_hash_raw(h)
|
|
234
|
+
else:
|
|
235
|
+
with open(content_input, encoding="utf-8") as f:
|
|
236
|
+
content_snapshot = f.read()
|
|
237
|
+
else:
|
|
238
|
+
content_snapshot = content_input
|
|
239
|
+
|
|
240
|
+
state_yaml = Card(
|
|
241
|
+
token_type="state",
|
|
242
|
+
producer_pcard_hash=pcard_hash,
|
|
243
|
+
vcard_dispatch_hash=vcard_dispatch_hash,
|
|
244
|
+
timestamp=timestamp,
|
|
245
|
+
agent_did=agent_did,
|
|
246
|
+
content_snapshot=content_snapshot,
|
|
247
|
+
).to_yaml()
|
|
248
|
+
|
|
249
|
+
state_hash = hash_string(state_yaml)
|
|
250
|
+
handle_name = f"mcard:state:{state_hash}"
|
|
251
|
+
ctx.repo.save_card_and_handle(
|
|
252
|
+
handle_name, state_hash, state_yaml, "execution_log",
|
|
253
|
+
timestamp=timestamp, replace=False,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
jsonl_emit_typed("state_emitted", {
|
|
257
|
+
"state_hash": state_hash,
|
|
258
|
+
"producer_pcard_hash": pcard_hash,
|
|
259
|
+
"vcard_dispatch_hash": vcard_dispatch_hash,
|
|
260
|
+
}, ctx.root)
|
|
261
|
+
|
|
262
|
+
if not ctx.zero_fs:
|
|
263
|
+
logs_dir = os.path.join(ctx.root, "data", "execution_logs")
|
|
264
|
+
os.makedirs(logs_dir, exist_ok=True)
|
|
265
|
+
unix_ts = int(time.time())
|
|
266
|
+
log_file = os.path.join(logs_dir, f"state_{unix_ts}_{state_hash[:8]}.yaml")
|
|
267
|
+
with open(log_file, "w", encoding="utf-8") as fh:
|
|
268
|
+
fh.write(state_yaml)
|
|
269
|
+
|
|
270
|
+
return state_hash
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def emit_state_failed(
|
|
274
|
+
ctx: CLMContext,
|
|
275
|
+
pcard_hash: str,
|
|
276
|
+
exit_code: str,
|
|
277
|
+
reason: str,
|
|
278
|
+
) -> None:
|
|
279
|
+
"""Emit a state-failed event for a PCard that did not complete."""
|
|
280
|
+
jsonl_emit_typed("state_failed", {
|
|
281
|
+
"pcard_hash": pcard_hash,
|
|
282
|
+
"exit_code": exit_code,
|
|
283
|
+
"reason": reason,
|
|
284
|
+
}, ctx.root)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def make_mcard_content(
|
|
288
|
+
content_hash: str,
|
|
289
|
+
content: str,
|
|
290
|
+
filename: str = "test.txt",
|
|
291
|
+
mime: str = "text/plain",
|
|
292
|
+
) -> str:
|
|
293
|
+
"""Return a canonical MCard YAML content block (Sprint 131.5: thin delegate).
|
|
294
|
+
|
|
295
|
+
Delegates to :class:`Card` so the unified model is the single source of
|
|
296
|
+
truth for serialization, while preserving the exact signature and output
|
|
297
|
+
that ``build_store``'s ``services.modules`` injection and the
|
|
298
|
+
``make_mcard_content`` CLM expression op depend on.
|
|
299
|
+
"""
|
|
300
|
+
return Card(
|
|
301
|
+
token_type="mcard",
|
|
302
|
+
g_time="sha256|2026-04-29T00:00:00+0800|Asia/Makassar",
|
|
303
|
+
content_hash=content_hash,
|
|
304
|
+
content=content,
|
|
305
|
+
source={"filename": filename, "mime_type": mime, "encoding": "inline"},
|
|
306
|
+
).to_yaml()
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
# Sprint 133.1: moved from layer0/db.py — parses MCard YAML, belongs with Card.
|
|
310
|
+
def parse_yaml_mcard(mcard_content_str: str) -> tuple[str | None, str | None, str | None]:
|
|
311
|
+
"""Extract content_hash, g_time, and source filename from MCard YAML."""
|
|
312
|
+
import re
|
|
313
|
+
hash_match = re.search(r'content_hash:\s*["\']?([a-fA-F0-9]{64})["\']?', mcard_content_str)
|
|
314
|
+
gtime_match = re.search(r'g_time:\s*["\']?([^"\n\']+)["\']?', mcard_content_str)
|
|
315
|
+
filename_match = re.search(r'filename:\s*["\']?([^"\n\']+)["\']?', mcard_content_str)
|
|
316
|
+
|
|
317
|
+
content_hash = hash_match.group(1) if hash_match else None
|
|
318
|
+
g_time = gtime_match.group(1) if gtime_match else None
|
|
319
|
+
source_filename = filename_match.group(1) if filename_match else None
|
|
320
|
+
|
|
321
|
+
return content_hash, g_time, source_filename
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Native acceleration dispatcher with transparent pure-Python fallback.
|
|
2
|
+
|
|
3
|
+
Provides high-performance in-memory bindings to the Rust core runtime (_rust)
|
|
4
|
+
via PyO3 when compiled wheels or maturin development environments are available.
|
|
5
|
+
Automatically falls back to pure-Python implementations when native extensions
|
|
6
|
+
are absent, ensuring zero runtime disruption in interpreted environments.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
from typing import Any, Callable, Optional, Union
|
|
13
|
+
|
|
14
|
+
from clm.cross_cutting.clm_logger import get_logger
|
|
15
|
+
|
|
16
|
+
_logger = get_logger("clm.native")
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
from clm import _rust # type: ignore[attr-defined]
|
|
20
|
+
HAS_RUST_ACCELERATION: bool = True
|
|
21
|
+
except (ImportError, ModuleNotFoundError):
|
|
22
|
+
try:
|
|
23
|
+
import clm_rust_core as _rust # type: ignore[no-redef]
|
|
24
|
+
HAS_RUST_ACCELERATION = True
|
|
25
|
+
except (ImportError, ModuleNotFoundError):
|
|
26
|
+
try:
|
|
27
|
+
import _rust # type: ignore[no-redef]
|
|
28
|
+
HAS_RUST_ACCELERATION = True
|
|
29
|
+
except (ImportError, ModuleNotFoundError):
|
|
30
|
+
_rust = None # type: ignore[assignment]
|
|
31
|
+
HAS_RUST_ACCELERATION = False
|
|
32
|
+
_logger.debug("Rust native extension (_rust) unavailable; utilizing pure-Python engine.")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def compute_blake3(data: Union[bytes, bytearray, memoryview, str]) -> str:
|
|
36
|
+
"""Compute cryptographic hash via native Rust engine if available, or Python fallback.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
data: Input bytes or string to hash.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Hex-encoded hash digest string.
|
|
43
|
+
"""
|
|
44
|
+
raw_bytes = data.encode("utf-8") if isinstance(data, str) else bytes(data)
|
|
45
|
+
|
|
46
|
+
if HAS_RUST_ACCELERATION and _rust is not None:
|
|
47
|
+
try:
|
|
48
|
+
return _rust.blake3_hash_bytes(raw_bytes)
|
|
49
|
+
except Exception as e:
|
|
50
|
+
_logger.warning(f"Native blake3_hash_bytes failed ({e}); falling back to Python.")
|
|
51
|
+
|
|
52
|
+
# Pure-Python fallback using layer0 cryptographic hash
|
|
53
|
+
from clm.layer0.hash import compute_blake3 as _l0_blake3
|
|
54
|
+
return _l0_blake3(raw_bytes)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def clm_hash_file_fast(path: str) -> str:
|
|
58
|
+
"""Compute content hash for a file, releasing GIL in Rust or using Python fallback.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
path: Filesystem path to the target file.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Hex-encoded content hash string.
|
|
65
|
+
"""
|
|
66
|
+
if HAS_RUST_ACCELERATION and _rust is not None:
|
|
67
|
+
try:
|
|
68
|
+
return _rust.clm_hash_file(path)
|
|
69
|
+
except Exception as e:
|
|
70
|
+
_logger.warning(f"Native clm_hash_file failed ({e}); falling back to Python.")
|
|
71
|
+
|
|
72
|
+
from clm.layer0.utils import clm_hash_file
|
|
73
|
+
return clm_hash_file(path)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def crdt_merge_fast(log_a_json: str, log_b_json: str) -> str:
|
|
77
|
+
"""Merge two CRDT logs idempotently via native Rust engine or pure-Python fallback.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
log_a_json: Primary CRDT log serialized as JSON.
|
|
81
|
+
log_b_json: Secondary CRDT log serialized as JSON.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Merged CRDT log serialized as JSON.
|
|
85
|
+
"""
|
|
86
|
+
if HAS_RUST_ACCELERATION and _rust is not None and hasattr(_rust, "crdt_merge"):
|
|
87
|
+
try:
|
|
88
|
+
return _rust.crdt_merge(log_a_json, log_b_json)
|
|
89
|
+
except Exception as e:
|
|
90
|
+
_logger.warning(f"Native crdt_merge failed ({e}); falling back to Python.")
|
|
91
|
+
|
|
92
|
+
# Pure Python JSON-level idempotent union fallback
|
|
93
|
+
try:
|
|
94
|
+
a = json.loads(log_a_json)
|
|
95
|
+
b = json.loads(log_b_json)
|
|
96
|
+
key = "entries" if "entries" in a else "events"
|
|
97
|
+
events_a = a.get(key, [])
|
|
98
|
+
events_b = b.get(key, [])
|
|
99
|
+
seen_ids = {e.get("event_id") for e in events_a if "event_id" in e}
|
|
100
|
+
for ev in events_b:
|
|
101
|
+
eid = ev.get("event_id")
|
|
102
|
+
if eid and eid not in seen_ids:
|
|
103
|
+
events_a.append(ev)
|
|
104
|
+
seen_ids.add(eid)
|
|
105
|
+
a[key] = events_a
|
|
106
|
+
return json.dumps(a)
|
|
107
|
+
except Exception:
|
|
108
|
+
return log_a_json
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
ManifestEvaluatorFn = Callable[[str], Any]
|
|
112
|
+
_manifest_evaluator: ManifestEvaluatorFn | None = None
|
|
113
|
+
_manifest_evaluator_resolver: Callable[[], ManifestEvaluatorFn | None] | None = None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def register_manifest_evaluator(evaluator: ManifestEvaluatorFn) -> None:
|
|
117
|
+
"""Register a manifest evaluator callback (Dependency Inversion for layer stratification)."""
|
|
118
|
+
global _manifest_evaluator
|
|
119
|
+
_manifest_evaluator = evaluator
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def register_manifest_evaluator_resolver(resolver: Callable[[], ManifestEvaluatorFn | None]) -> None:
|
|
123
|
+
"""Register a lazy resolver for the manifest evaluator."""
|
|
124
|
+
global _manifest_evaluator_resolver
|
|
125
|
+
_manifest_evaluator_resolver = resolver
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def evaluate_manifest(manifest_yaml: str) -> str:
|
|
129
|
+
"""Evaluate manifest using in-memory native CPN-VM or pure-Python verifier.
|
|
130
|
+
|
|
131
|
+
Propagates active Cordis monadic context (session_id, agent_did, trace_id)
|
|
132
|
+
across the FFI boundary. Falls back to Python verifier if Rust extension is absent
|
|
133
|
+
or encounters error.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
manifest_yaml: Raw YAML string of the CLM specification.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Evaluation result string or generated MCard handle.
|
|
140
|
+
"""
|
|
141
|
+
from clm.layer0.context import CLMContext
|
|
142
|
+
current_ctx = CLMContext.current()
|
|
143
|
+
context_json: Optional[str] = None
|
|
144
|
+
if current_ctx is not None:
|
|
145
|
+
context_json = json.dumps({
|
|
146
|
+
"session_id": getattr(current_ctx, "session_id", None),
|
|
147
|
+
"agent_did": getattr(current_ctx, "agent_did", None),
|
|
148
|
+
"trace_id": getattr(current_ctx, "trace_id", None),
|
|
149
|
+
"zero_fs": getattr(current_ctx, "zero_fs", False),
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
if HAS_RUST_ACCELERATION and _rust is not None:
|
|
153
|
+
try:
|
|
154
|
+
return _rust.evaluate_manifest_fast(manifest_yaml, context_json)
|
|
155
|
+
except Exception as e:
|
|
156
|
+
_logger.warning(f"Native evaluate_manifest_fast failed ({e}); falling back to Python.")
|
|
157
|
+
|
|
158
|
+
if _manifest_evaluator is not None:
|
|
159
|
+
return _manifest_evaluator(manifest_yaml)
|
|
160
|
+
|
|
161
|
+
if _manifest_evaluator_resolver is not None:
|
|
162
|
+
evaluator = _manifest_evaluator_resolver()
|
|
163
|
+
if evaluator is not None:
|
|
164
|
+
return evaluator(manifest_yaml)
|
|
165
|
+
|
|
166
|
+
raise RuntimeError(
|
|
167
|
+
"No manifest evaluator registered with cross_cutting.native. "
|
|
168
|
+
"Initialize Layer 1 verifier (clm.layer1.verifier) before evaluating manifests."
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def evaluate_in_process(clm_root: str, clm_file: str, payload: Optional[str] = None) -> Optional[tuple[int, str]]:
|
|
173
|
+
"""Direct in-process evaluation of a CLM manifest via PyO3 C-extension without process forks.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
(exit_code, output) tuple, or None if native extension is unavailable.
|
|
177
|
+
"""
|
|
178
|
+
if HAS_RUST_ACCELERATION and _rust is not None and hasattr(_rust, "evaluate_in_process"):
|
|
179
|
+
try:
|
|
180
|
+
return _rust.evaluate_in_process(clm_root, clm_file, payload)
|
|
181
|
+
except Exception as e:
|
|
182
|
+
_logger.warning(f"Native evaluate_in_process failed ({e}); falling back.")
|
|
183
|
+
return None
|
|
184
|
+
return None
|
|
185
|
+
|