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,338 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core builtin operations for PythonRuntime.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from clm.cross_cutting.config.config_constants import URL_FETCH_TIMEOUT_SECS
|
|
9
|
+
from clm.layer0.model.card import MCard
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def op_identity(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
13
|
+
"""Identity operation - returns target content unchanged."""
|
|
14
|
+
return target.get_content()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def op_transform(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
18
|
+
"""Transform operation - applies a named transformation."""
|
|
19
|
+
transforms = {
|
|
20
|
+
"upper_case": lambda t: t.get_content().decode("utf-8").upper().encode("utf-8"),
|
|
21
|
+
"count_bytes": lambda t: len(t.get_content()),
|
|
22
|
+
}
|
|
23
|
+
func = impl.get("transform_function")
|
|
24
|
+
return transforms.get(func, lambda t: t.get_content())(target)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def op_arithmetic(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
28
|
+
"""Arithmetic operation on numeric target content."""
|
|
29
|
+
params = {**impl.get("params", {}), **ctx}
|
|
30
|
+
op, operand = params.get("op"), params.get("operand")
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
val = float(target.get_content().decode("utf-8"))
|
|
34
|
+
except ValueError:
|
|
35
|
+
return "Error: Target content is not a valid number"
|
|
36
|
+
|
|
37
|
+
ops = {
|
|
38
|
+
"add": lambda x, y: x + y,
|
|
39
|
+
"sub": lambda x, y: x - y,
|
|
40
|
+
"mul": lambda x, y: x * y,
|
|
41
|
+
"div": lambda x, y: x / y if y != 0 else "Error: Division by zero",
|
|
42
|
+
}
|
|
43
|
+
return ops.get(op, lambda x, y: f"Error: Unknown operation '{op}'")(val, operand)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def op_string(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
47
|
+
"""String operation on target content."""
|
|
48
|
+
params = {**impl.get("params", {}), **ctx}
|
|
49
|
+
func = params.get("func")
|
|
50
|
+
s = target.get_content().decode("utf-8")
|
|
51
|
+
|
|
52
|
+
ops = {
|
|
53
|
+
"reverse": lambda: s[::-1],
|
|
54
|
+
"len": lambda: len(s),
|
|
55
|
+
"split": lambda: s.split(params.get("delimiter", " ")),
|
|
56
|
+
}
|
|
57
|
+
return ops.get(func, lambda: f"Error: Unknown function '{func}'")()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def op_fetch_url(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
61
|
+
"""Fetch content from a URL."""
|
|
62
|
+
|
|
63
|
+
from clm.cross_cutting.utils.url_safety import safe_urlopen
|
|
64
|
+
|
|
65
|
+
url = target.get_content().decode("utf-8").strip()
|
|
66
|
+
try:
|
|
67
|
+
with safe_urlopen(url, timeout=URL_FETCH_TIMEOUT_SECS) as resp:
|
|
68
|
+
return resp.read().decode("utf-8")[:1000]
|
|
69
|
+
except (OSError, ValueError, UnicodeDecodeError) as e:
|
|
70
|
+
return f"Error fetching URL: {e}"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def op_session_record(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
74
|
+
"""P2P Session Recording operation."""
|
|
75
|
+
config = impl.get("config", {})
|
|
76
|
+
ctx_params = ctx.get("params", {})
|
|
77
|
+
|
|
78
|
+
# Extract session_id from various sources
|
|
79
|
+
session_id = ctx.get("sessionId") or ctx_params.get("sessionId")
|
|
80
|
+
|
|
81
|
+
# Check config with potential interpolation
|
|
82
|
+
if not session_id and "sessionId" in config:
|
|
83
|
+
val = config["sessionId"]
|
|
84
|
+
if isinstance(val, str) and val.startswith("${") and val.endswith("}"):
|
|
85
|
+
key = val[9:-1] # strip '${params.' and '}'
|
|
86
|
+
if "." in key:
|
|
87
|
+
key = key.split(".")[-1]
|
|
88
|
+
session_id = ctx.get(key) or ctx_params.get(key)
|
|
89
|
+
else:
|
|
90
|
+
session_id = val
|
|
91
|
+
|
|
92
|
+
# Fallback to target content inspection
|
|
93
|
+
if not session_id:
|
|
94
|
+
try:
|
|
95
|
+
content = target.get_content().decode("utf-8")
|
|
96
|
+
data = json.loads(content)
|
|
97
|
+
if isinstance(data, dict):
|
|
98
|
+
session_id = data.get("sessionId")
|
|
99
|
+
except json.JSONDecodeError:
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
"success": True,
|
|
104
|
+
"session_id": session_id,
|
|
105
|
+
"message": f"Session recording initialized for {session_id}",
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def op_precondition_witness(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
110
|
+
"""Precondition event generation operation.
|
|
111
|
+
Generates a simple PCard to act as the V_Pre gate and logs it.
|
|
112
|
+
"""
|
|
113
|
+
import json
|
|
114
|
+
from datetime import datetime, timezone
|
|
115
|
+
|
|
116
|
+
from clm.layer0.model.pcard import PCard
|
|
117
|
+
from clm.layer0.model.vcard import VCardPre
|
|
118
|
+
|
|
119
|
+
pcard_hash = ctx.get("pcard_hash", "")
|
|
120
|
+
verification_evidence = ctx.get("verification_evidence")
|
|
121
|
+
|
|
122
|
+
# We could derive managed_event_types from preconditions or inputs.
|
|
123
|
+
# For now, let's look for a specific key in the target or assume a default.
|
|
124
|
+
# In a fully fleshed out system, this might be dynamically mapped.
|
|
125
|
+
managed_event_types = []
|
|
126
|
+
|
|
127
|
+
if isinstance(target, PCard):
|
|
128
|
+
v_pre_pcard = target.create_vcard(
|
|
129
|
+
vcard_class=VCardPre,
|
|
130
|
+
managed_event_types=managed_event_types,
|
|
131
|
+
version="1.0",
|
|
132
|
+
type="vcard-pre",
|
|
133
|
+
pcard_hash=pcard_hash,
|
|
134
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
135
|
+
target_hash=target.hash,
|
|
136
|
+
verification_evidence=verification_evidence,
|
|
137
|
+
)
|
|
138
|
+
else:
|
|
139
|
+
content = {
|
|
140
|
+
"vcard": {
|
|
141
|
+
"version": "1.0",
|
|
142
|
+
"type": "vcard-pre",
|
|
143
|
+
"pcard_hash": pcard_hash,
|
|
144
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
145
|
+
"target_hash": target.hash if target else None,
|
|
146
|
+
"managed_event_types": managed_event_types,
|
|
147
|
+
"wrapped_pcard_hash": target.hash if target else None,
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if verification_evidence:
|
|
151
|
+
content["vcard"]["verification_evidence"] = verification_evidence
|
|
152
|
+
|
|
153
|
+
# We wrap it directly since VCardPre inherits from VCard which inherits from PCard
|
|
154
|
+
v_pre_pcard = VCardPre(json.dumps(content))
|
|
155
|
+
|
|
156
|
+
collection = ctx.get("collection")
|
|
157
|
+
if collection:
|
|
158
|
+
vcard_hash = collection.add(v_pre_pcard)
|
|
159
|
+
else:
|
|
160
|
+
vcard_hash = v_pre_pcard.hash
|
|
161
|
+
|
|
162
|
+
log_db = ctx.get("log_db")
|
|
163
|
+
if log_db:
|
|
164
|
+
log_db.add(
|
|
165
|
+
MCard(
|
|
166
|
+
f"Execution Trace: PREP Phase Event | PCard: {pcard_hash} | Target: {target.hash} | V_Pre: {vcard_hash}"
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
# Register the v_pre with the execution engine or log if needed.
|
|
170
|
+
# It's now acting as a hook waiting for events.
|
|
171
|
+
|
|
172
|
+
return vcard_hash
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def op_postcondition_witness(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
176
|
+
"""Postcondition event generation operation.
|
|
177
|
+
Generates a simple PCard to act as the V_Post gate and logs it.
|
|
178
|
+
"""
|
|
179
|
+
import json
|
|
180
|
+
from datetime import datetime, timezone
|
|
181
|
+
|
|
182
|
+
from clm.layer0.model.pcard import PCard
|
|
183
|
+
from clm.layer0.model.vcard import VCardPost
|
|
184
|
+
|
|
185
|
+
pcard_hash = ctx.get("pcard_hash", "")
|
|
186
|
+
output = ctx.get("execution_output", "")
|
|
187
|
+
alignment_score = ctx.get("alignment_score")
|
|
188
|
+
invariants_preserved = ctx.get("invariants_preserved", True)
|
|
189
|
+
execution_telemetry = ctx.get("execution_telemetry")
|
|
190
|
+
governance_telemetry = ctx.get("governance_telemetry")
|
|
191
|
+
|
|
192
|
+
if isinstance(output, MCard):
|
|
193
|
+
output_repr = output.hash
|
|
194
|
+
elif isinstance(output, dict):
|
|
195
|
+
output_repr = json.dumps(output, sort_keys=True, default=str)[:512]
|
|
196
|
+
else:
|
|
197
|
+
output_repr = str(output)[:512]
|
|
198
|
+
|
|
199
|
+
# We could derive managed_event_types from postconditions or outputs.
|
|
200
|
+
# For now, let's extract it from the target if it specifies types to dispatch.
|
|
201
|
+
managed_event_types = []
|
|
202
|
+
try:
|
|
203
|
+
if isinstance(output, dict) and "dispatch_types" in output:
|
|
204
|
+
managed_event_types = output["dispatch_types"]
|
|
205
|
+
except Exception:
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
if isinstance(target, PCard):
|
|
209
|
+
v_post_pcard = target.create_vcard(
|
|
210
|
+
vcard_class=VCardPost,
|
|
211
|
+
managed_event_types=managed_event_types,
|
|
212
|
+
version="1.0",
|
|
213
|
+
type="vcard-post",
|
|
214
|
+
pcard_hash=pcard_hash,
|
|
215
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
216
|
+
output_repr=output_repr,
|
|
217
|
+
alignment_score=alignment_score,
|
|
218
|
+
invariants_preserved=invariants_preserved,
|
|
219
|
+
execution_telemetry=execution_telemetry,
|
|
220
|
+
governance_telemetry=governance_telemetry,
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
content = {
|
|
224
|
+
"vcard": {
|
|
225
|
+
"version": "1.0",
|
|
226
|
+
"type": "vcard-post",
|
|
227
|
+
"pcard_hash": pcard_hash,
|
|
228
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
229
|
+
"output_repr": output_repr,
|
|
230
|
+
"alignment_score": alignment_score,
|
|
231
|
+
"invariants_preserved": invariants_preserved,
|
|
232
|
+
"managed_event_types": managed_event_types,
|
|
233
|
+
"wrapped_pcard_hash": target.hash if target else None,
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if execution_telemetry:
|
|
238
|
+
content["vcard"]["execution_telemetry"] = execution_telemetry
|
|
239
|
+
if governance_telemetry:
|
|
240
|
+
content["vcard"]["governance_telemetry"] = governance_telemetry
|
|
241
|
+
|
|
242
|
+
v_post_pcard = VCardPost(json.dumps(content))
|
|
243
|
+
|
|
244
|
+
collection = ctx.get("collection")
|
|
245
|
+
if collection:
|
|
246
|
+
vcard_hash = collection.add(v_post_pcard)
|
|
247
|
+
else:
|
|
248
|
+
vcard_hash = v_post_pcard.hash
|
|
249
|
+
|
|
250
|
+
log_db = ctx.get("log_db")
|
|
251
|
+
if log_db:
|
|
252
|
+
log_db.add(
|
|
253
|
+
MCard(
|
|
254
|
+
f"Execution Trace: POST Phase Event | PCard: {pcard_hash} | Target: {target.hash} | V_Post: {vcard_hash} | Score: {alignment_score}"
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Trigger the dispatcher immediately upon generation
|
|
259
|
+
v_post_pcard.dispatch_events(log_db)
|
|
260
|
+
|
|
261
|
+
return vcard_hash
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def op_invoke_library(impl: dict, target: MCard, ctx: dict) -> Any:
|
|
265
|
+
"""Invoke a library function directly by its signature/reference."""
|
|
266
|
+
import importlib
|
|
267
|
+
|
|
268
|
+
try:
|
|
269
|
+
from clm.cross_cutting.config.settings import settings
|
|
270
|
+
|
|
271
|
+
allowed_imports = settings.ptr.allowed_imports
|
|
272
|
+
safe_builtins = settings.ptr.safe_builtins
|
|
273
|
+
except ImportError:
|
|
274
|
+
allowed_imports = {}
|
|
275
|
+
safe_builtins = set()
|
|
276
|
+
|
|
277
|
+
module_name = impl.get("module")
|
|
278
|
+
func_name = impl.get("function")
|
|
279
|
+
|
|
280
|
+
if not func_name:
|
|
281
|
+
return "Error: No function specified in invoke_library"
|
|
282
|
+
|
|
283
|
+
# Resolve function
|
|
284
|
+
if module_name:
|
|
285
|
+
if module_name not in allowed_imports and module_name != "math":
|
|
286
|
+
return f"Error: Import of module '{module_name}' is not allowed"
|
|
287
|
+
try:
|
|
288
|
+
module = importlib.import_module(module_name)
|
|
289
|
+
func = getattr(module, func_name)
|
|
290
|
+
except Exception as e:
|
|
291
|
+
return f"Error: Could not load {module_name}.{func_name}: {e}"
|
|
292
|
+
else:
|
|
293
|
+
import builtins as builtins_module
|
|
294
|
+
|
|
295
|
+
if func_name not in safe_builtins:
|
|
296
|
+
return f"Error: Builtin function '{func_name}' is not allowed"
|
|
297
|
+
func = getattr(builtins_module, func_name)
|
|
298
|
+
|
|
299
|
+
# Collect inputs
|
|
300
|
+
input_defs = impl.get("inputs", {})
|
|
301
|
+
# Inputs might be a list or a dict in the spec
|
|
302
|
+
input_keys = (
|
|
303
|
+
list(input_defs.keys())
|
|
304
|
+
if isinstance(input_defs, dict)
|
|
305
|
+
else (input_defs if isinstance(input_defs, list) else [])
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
args = []
|
|
309
|
+
# Fetch from context, or target if no input keys defined and we just want to pass the target
|
|
310
|
+
if not input_keys:
|
|
311
|
+
try:
|
|
312
|
+
val = target.get_content().decode("utf-8")
|
|
313
|
+
# If it's a number, cast it
|
|
314
|
+
if val.lstrip("-").replace(".", "", 1).isdigit():
|
|
315
|
+
val = float(val) if "." in val else int(val)
|
|
316
|
+
args.append(val)
|
|
317
|
+
except Exception:
|
|
318
|
+
args.append(target.get_content())
|
|
319
|
+
else:
|
|
320
|
+
for key in input_keys:
|
|
321
|
+
val = ctx.get(key)
|
|
322
|
+
if val is None and key == "target":
|
|
323
|
+
try:
|
|
324
|
+
target_val = target.get_content().decode("utf-8")
|
|
325
|
+
if target_val.lstrip("-").replace(".", "", 1).isdigit():
|
|
326
|
+
target_val = (
|
|
327
|
+
float(target_val) if "." in target_val else int(target_val)
|
|
328
|
+
)
|
|
329
|
+
val = target_val
|
|
330
|
+
except Exception:
|
|
331
|
+
val = target.get_content()
|
|
332
|
+
args.append(val)
|
|
333
|
+
|
|
334
|
+
# Invoke
|
|
335
|
+
try:
|
|
336
|
+
return func(*args)
|
|
337
|
+
except Exception as e:
|
|
338
|
+
return f"Error invoking {func_name}: {e}"
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Baldwin Operations Dispatcher (DEL-388-03).
|
|
2
|
+
|
|
3
|
+
Unified front-end for Baldwin Modularity Operators built directly on top of
|
|
4
|
+
the existing OperationRegistry (clm.layer1.operations.base).
|
|
5
|
+
Provides syntactic closure validation, semantic closure checks, and declarative dispatch.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any, Callable
|
|
10
|
+
|
|
11
|
+
from clm.layer0.model.card import MCard
|
|
12
|
+
from clm.layer1.operations.augment import op_augment
|
|
13
|
+
from clm.layer1.operations.base import OperationRegistry
|
|
14
|
+
from clm.layer1.operations.exclude import op_exclude
|
|
15
|
+
from clm.layer1.operations.invert import op_invert
|
|
16
|
+
from clm.layer1.operations.port import op_port
|
|
17
|
+
from clm.layer1.operations.split import op_split
|
|
18
|
+
from clm.layer1.operations.substitute import op_substitute
|
|
19
|
+
|
|
20
|
+
BALDWIN_OPERATIONS: dict[str, Callable] = {
|
|
21
|
+
"split": op_split,
|
|
22
|
+
"substitute": op_substitute,
|
|
23
|
+
"augment": op_augment,
|
|
24
|
+
"exclude": op_exclude,
|
|
25
|
+
"invert": op_invert,
|
|
26
|
+
"port": op_port,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def verify_syntactic_closure(manifest: dict[str, Any]) -> bool:
|
|
31
|
+
"""Validate that a manifest satisfies triadic syntactic closure.
|
|
32
|
+
|
|
33
|
+
Per spec/40-behavior/baldwin_monadic_pcard_algebra.md §0:
|
|
34
|
+
Every operator application must preserve:
|
|
35
|
+
1. abstract_spec (or abstract)
|
|
36
|
+
2. concrete_impl (or concrete)
|
|
37
|
+
3. balanced_exp (or balanced)
|
|
38
|
+
"""
|
|
39
|
+
if not isinstance(manifest, dict):
|
|
40
|
+
return False
|
|
41
|
+
has_abstract = "abstract_spec" in manifest or "abstract" in manifest
|
|
42
|
+
has_concrete = "concrete_impl" in manifest or "concrete" in manifest
|
|
43
|
+
has_balanced = "balanced_exp" in manifest or "balanced" in manifest
|
|
44
|
+
return bool(has_abstract and has_concrete and has_balanced)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def verify_semantic_closure(result: dict[str, Any]) -> bool:
|
|
48
|
+
"""Validate that the operation result forms a valid morphism in Poly(X)."""
|
|
49
|
+
if not isinstance(result, dict):
|
|
50
|
+
return False
|
|
51
|
+
if not result.get("success", False):
|
|
52
|
+
return False
|
|
53
|
+
# If the result returns a manifest or branch manifests, check closure
|
|
54
|
+
if "manifest" in result:
|
|
55
|
+
return verify_syntactic_closure(result["manifest"])
|
|
56
|
+
if "branch_a" in result and "branch_b" in result:
|
|
57
|
+
m_a = result["branch_a"].get("manifest", {})
|
|
58
|
+
m_b = result["branch_b"].get("manifest", {})
|
|
59
|
+
return verify_syntactic_closure(m_a) and verify_syntactic_closure(m_b)
|
|
60
|
+
return True
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def register_baldwin_operations(registry: OperationRegistry) -> None:
|
|
64
|
+
"""Register the six Baldwin modularity operators onto an existing OperationRegistry."""
|
|
65
|
+
registry.register_many(BALDWIN_OPERATIONS)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_baldwin_registry() -> OperationRegistry:
|
|
69
|
+
"""Construct an OperationRegistry with all default and Baldwin operations registered."""
|
|
70
|
+
from clm.layer1.operations import DEFAULT_OPERATIONS
|
|
71
|
+
|
|
72
|
+
reg = OperationRegistry()
|
|
73
|
+
reg.register_many(DEFAULT_OPERATIONS)
|
|
74
|
+
reg.register_many(BALDWIN_OPERATIONS)
|
|
75
|
+
return reg
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def dispatch_baldwin_operation(
|
|
79
|
+
op_name: str,
|
|
80
|
+
impl: dict[str, Any] | None = None,
|
|
81
|
+
target: MCard | None = None,
|
|
82
|
+
ctx: dict[str, Any] | None = None,
|
|
83
|
+
registry: OperationRegistry | None = None,
|
|
84
|
+
) -> Any:
|
|
85
|
+
"""Dispatch a Baldwin operation by name.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
op_name: Name of operator ('split', 'substitute', 'augment', 'exclude', 'invert', 'port').
|
|
89
|
+
impl: Implementation parameters.
|
|
90
|
+
target: Target MCard to transform (if None, creates empty placeholder MCard).
|
|
91
|
+
ctx: Execution context.
|
|
92
|
+
registry: Optional custom OperationRegistry.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Operation execution result.
|
|
96
|
+
"""
|
|
97
|
+
impl = impl or {}
|
|
98
|
+
ctx = ctx or {}
|
|
99
|
+
if target is None:
|
|
100
|
+
target = MCard("abstract_spec:\n type: default\nconcrete_impl:\n runtime: python\nbalanced_exp:\n invariants: []")
|
|
101
|
+
|
|
102
|
+
reg = registry or get_baldwin_registry()
|
|
103
|
+
handler = reg.get(op_name)
|
|
104
|
+
if handler is None:
|
|
105
|
+
raise KeyError(f"Baldwin operation '{op_name}' not found in registry. Registered: {reg.list_operations()}")
|
|
106
|
+
|
|
107
|
+
result = handler(impl, target, ctx)
|
|
108
|
+
return result
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class BaldwinOperationDispatcher:
|
|
112
|
+
"""High-level dispatcher for Baldwin modularity operators."""
|
|
113
|
+
|
|
114
|
+
def __init__(self, registry: OperationRegistry | None = None):
|
|
115
|
+
self.registry = registry or get_baldwin_registry()
|
|
116
|
+
|
|
117
|
+
def split(self, target: MCard, impl: dict[str, Any] | None = None, ctx: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
118
|
+
return dispatch_baldwin_operation("split", impl, target, ctx, self.registry)
|
|
119
|
+
|
|
120
|
+
def substitute(self, target: MCard, impl: dict[str, Any] | None = None, ctx: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
121
|
+
return dispatch_baldwin_operation("substitute", impl, target, ctx, self.registry)
|
|
122
|
+
|
|
123
|
+
def augment(self, target: MCard, impl: dict[str, Any] | None = None, ctx: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
124
|
+
return dispatch_baldwin_operation("augment", impl, target, ctx, self.registry)
|
|
125
|
+
|
|
126
|
+
def exclude(self, target: MCard, impl: dict[str, Any] | None = None, ctx: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
127
|
+
return dispatch_baldwin_operation("exclude", impl, target, ctx, self.registry)
|
|
128
|
+
|
|
129
|
+
def invert(self, target: MCard, impl: dict[str, Any] | None = None, ctx: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
130
|
+
return dispatch_baldwin_operation("invert", impl, target, ctx, self.registry)
|
|
131
|
+
|
|
132
|
+
def port(self, target: MCard, impl: dict[str, Any] | None = None, ctx: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
133
|
+
return dispatch_baldwin_operation("port", impl, target, ctx, self.registry)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
__all__ = [
|
|
137
|
+
"BALDWIN_OPERATIONS",
|
|
138
|
+
"verify_syntactic_closure",
|
|
139
|
+
"verify_semantic_closure",
|
|
140
|
+
"register_baldwin_operations",
|
|
141
|
+
"get_baldwin_registry",
|
|
142
|
+
"dispatch_baldwin_operation",
|
|
143
|
+
"BaldwinOperationDispatcher",
|
|
144
|
+
]
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Baldwin Exclude Operator (DEL-388-02).
|
|
2
|
+
|
|
3
|
+
Pruning Operator (-): A(B) -> A(-B).
|
|
4
|
+
Prunes constraints, steps, or capabilities from a CLM manifest,
|
|
5
|
+
archives the excluded content as an audit trail record, and enforces
|
|
6
|
+
triadic syntactic closure on the retained structure.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import copy
|
|
11
|
+
import time
|
|
12
|
+
from dataclasses import asdict, dataclass
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
from clm.layer0.model.card import MCard
|
|
18
|
+
from clm.layer0.utils import clm_hash_string
|
|
19
|
+
from clm.layer1.operations.split import _parse_manifest, ensure_triadic_closure
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class BaldwinAuditRecord:
|
|
24
|
+
"""Audit record preserving provenance for excluded/pruned components."""
|
|
25
|
+
operator: str
|
|
26
|
+
target_id: str
|
|
27
|
+
excluded_hash: str
|
|
28
|
+
excluded_content: str
|
|
29
|
+
timestamp: str
|
|
30
|
+
details: dict[str, Any]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def op_exclude(impl: dict[str, Any], target: MCard, ctx: dict[str, Any]) -> dict[str, Any]:
|
|
34
|
+
"""Execute the Baldwin Exclude (-) operation.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
impl: Configuration dict for exclude:
|
|
38
|
+
exclude_path (str): Dot-separated path or key to prune.
|
|
39
|
+
target: Target MCard to prune.
|
|
40
|
+
ctx: Execution context.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Dict containing the pruned manifest, new MCard, audit record, and closure proof.
|
|
44
|
+
"""
|
|
45
|
+
manifest = _parse_manifest(target)
|
|
46
|
+
|
|
47
|
+
exclude_path = impl.get("exclude_path", ctx.get("exclude_path", ""))
|
|
48
|
+
if not exclude_path:
|
|
49
|
+
# Check alternative parameter names
|
|
50
|
+
exclude_path = impl.get("target_id", ctx.get("target_id", ""))
|
|
51
|
+
|
|
52
|
+
updated = copy.deepcopy(manifest)
|
|
53
|
+
excluded_val: Any = None
|
|
54
|
+
|
|
55
|
+
if exclude_path:
|
|
56
|
+
path_str = exclude_path.strip().lstrip(".")
|
|
57
|
+
parts = [p for p in path_str.split(".") if p]
|
|
58
|
+
|
|
59
|
+
# Retrieve value before pruning
|
|
60
|
+
curr = updated
|
|
61
|
+
for p in parts[:-1]:
|
|
62
|
+
if isinstance(curr, dict) and p in curr:
|
|
63
|
+
curr = curr[p]
|
|
64
|
+
else:
|
|
65
|
+
curr = None
|
|
66
|
+
break
|
|
67
|
+
if isinstance(curr, dict) and parts and parts[-1] in curr:
|
|
68
|
+
excluded_val = curr.pop(parts[-1])
|
|
69
|
+
else:
|
|
70
|
+
# Default: prune an optional or deprecated section if found
|
|
71
|
+
for candidate in ["deprecated", "debug", "legacy", "metadata"]:
|
|
72
|
+
if candidate in updated:
|
|
73
|
+
exclude_path = candidate
|
|
74
|
+
excluded_val = updated.pop(candidate)
|
|
75
|
+
break
|
|
76
|
+
|
|
77
|
+
excluded_str = yaml.dump(excluded_val, default_flow_style=False) if excluded_val is not None else ""
|
|
78
|
+
excl_hash = clm_hash_string(excluded_str) if excluded_str else ""
|
|
79
|
+
ts = time.strftime("%Y-%m-%dT%H:%M:%S%z")
|
|
80
|
+
|
|
81
|
+
audit = BaldwinAuditRecord(
|
|
82
|
+
operator="exclude",
|
|
83
|
+
target_id=exclude_path or "none",
|
|
84
|
+
excluded_hash=excl_hash,
|
|
85
|
+
excluded_content=excluded_str,
|
|
86
|
+
timestamp=ts,
|
|
87
|
+
details={"retained_keys": list(updated.keys())},
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
final_manifest = ensure_triadic_closure(updated)
|
|
91
|
+
yaml_content = yaml.dump(final_manifest, default_flow_style=False)
|
|
92
|
+
new_card = MCard(yaml_content)
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
"success": True,
|
|
96
|
+
"operator": "exclude",
|
|
97
|
+
"exclude_path": exclude_path,
|
|
98
|
+
"syntactic_closure": True,
|
|
99
|
+
"audit": asdict(audit),
|
|
100
|
+
"manifest": final_manifest,
|
|
101
|
+
"hash": new_card.hash,
|
|
102
|
+
"content": yaml_content,
|
|
103
|
+
"mcard": new_card,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
__all__ = ["op_exclude", "BaldwinAuditRecord"]
|