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,230 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Lambda Term - Algebraic Data Type for Lambda Calculus
|
|
3
|
+
|
|
4
|
+
Represents Lambda Calculus terms as content-addressable MCards.
|
|
5
|
+
Each term variant is stored as JSON in MCard content, with sub-terms
|
|
6
|
+
referenced by their SHA-256 hashes for structural sharing.
|
|
7
|
+
|
|
8
|
+
The three term constructors mirror the BNF grammar:
|
|
9
|
+
M, N ::= x | λx.M | M N
|
|
10
|
+
|
|
11
|
+
This module provides Python parity with mcard-js/src/ptr/lambda/LambdaTerm.ts
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from typing import Literal
|
|
17
|
+
|
|
18
|
+
from clm.layer0.model.card import MCard
|
|
19
|
+
from clm.layer2.card_collection import CardCollection
|
|
20
|
+
|
|
21
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
# Lambda Term ADT
|
|
23
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class VarTerm:
|
|
28
|
+
"""Variable term: x"""
|
|
29
|
+
|
|
30
|
+
tag: Literal["Var"] = "Var"
|
|
31
|
+
name: str = ""
|
|
32
|
+
|
|
33
|
+
def __init__(self, name: str):
|
|
34
|
+
object.__setattr__(self, "name", name)
|
|
35
|
+
object.__setattr__(self, "tag", "Var")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class AbsTerm:
|
|
40
|
+
"""Abstraction term: λx.M - Body is stored as MCard hash"""
|
|
41
|
+
|
|
42
|
+
tag: Literal["Abs"] = "Abs"
|
|
43
|
+
param: str = ""
|
|
44
|
+
body: str = "" # MCard hash of body term
|
|
45
|
+
|
|
46
|
+
def __init__(self, param: str, body: str):
|
|
47
|
+
object.__setattr__(self, "param", param)
|
|
48
|
+
object.__setattr__(self, "body", body)
|
|
49
|
+
object.__setattr__(self, "tag", "Abs")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class AppTerm:
|
|
54
|
+
"""Application term: M N - Both func and arg are MCard hashes"""
|
|
55
|
+
|
|
56
|
+
tag: Literal["App"] = "App"
|
|
57
|
+
func: str = "" # MCard hash of function
|
|
58
|
+
arg: str = "" # MCard hash of argument
|
|
59
|
+
|
|
60
|
+
def __init__(self, func: str, arg: str):
|
|
61
|
+
object.__setattr__(self, "func", func)
|
|
62
|
+
object.__setattr__(self, "arg", arg)
|
|
63
|
+
object.__setattr__(self, "tag", "App")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
LambdaTerm = VarTerm | AbsTerm | AppTerm
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
70
|
+
# Constructors (Smart Constructors)
|
|
71
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def mk_var(name: str) -> VarTerm:
|
|
75
|
+
"""Create a variable term"""
|
|
76
|
+
return VarTerm(name=name)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def mk_abs(param: str, body_hash: str) -> AbsTerm:
|
|
80
|
+
"""Create an abstraction term"""
|
|
81
|
+
return AbsTerm(param=param, body=body_hash)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def mk_app(func_hash: str, arg_hash: str) -> AppTerm:
|
|
85
|
+
"""Create an application term"""
|
|
86
|
+
return AppTerm(func=func_hash, arg=arg_hash)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
90
|
+
# Serialization
|
|
91
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def serialize_term(term: LambdaTerm) -> str:
|
|
95
|
+
"""Serialize a Lambda term to MCard content (JSON string)"""
|
|
96
|
+
if isinstance(term, VarTerm):
|
|
97
|
+
return json.dumps({"tag": "Var", "name": term.name})
|
|
98
|
+
elif isinstance(term, AbsTerm):
|
|
99
|
+
return json.dumps({"tag": "Abs", "param": term.param, "body": term.body})
|
|
100
|
+
elif isinstance(term, AppTerm):
|
|
101
|
+
return json.dumps({"tag": "App", "func": term.func, "arg": term.arg})
|
|
102
|
+
else:
|
|
103
|
+
raise ValueError(f"Unknown term type: {type(term)}")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def deserialize_term(content: str) -> LambdaTerm:
|
|
107
|
+
"""Deserialize MCard content to Lambda term"""
|
|
108
|
+
parsed = json.loads(content)
|
|
109
|
+
|
|
110
|
+
if not parsed.get("tag"):
|
|
111
|
+
raise ValueError("Invalid Lambda term: missing tag")
|
|
112
|
+
|
|
113
|
+
tag = parsed["tag"]
|
|
114
|
+
|
|
115
|
+
if tag == "Var":
|
|
116
|
+
if not isinstance(parsed.get("name"), str):
|
|
117
|
+
raise ValueError("Invalid Var term: name must be string")
|
|
118
|
+
return mk_var(parsed["name"])
|
|
119
|
+
|
|
120
|
+
elif tag == "Abs":
|
|
121
|
+
if not isinstance(parsed.get("param"), str) or not isinstance(
|
|
122
|
+
parsed.get("body"), str
|
|
123
|
+
):
|
|
124
|
+
raise ValueError("Invalid Abs term: param and body must be strings")
|
|
125
|
+
return mk_abs(parsed["param"], parsed["body"])
|
|
126
|
+
|
|
127
|
+
elif tag == "App":
|
|
128
|
+
if not isinstance(parsed.get("func"), str) or not isinstance(
|
|
129
|
+
parsed.get("arg"), str
|
|
130
|
+
):
|
|
131
|
+
raise ValueError("Invalid App term: func and arg must be strings")
|
|
132
|
+
return mk_app(parsed["func"], parsed["arg"])
|
|
133
|
+
|
|
134
|
+
else:
|
|
135
|
+
raise ValueError(f"Unknown Lambda term tag: {tag}")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def term_to_mcard(term: LambdaTerm) -> MCard:
|
|
139
|
+
"""Create an MCard from a Lambda term"""
|
|
140
|
+
return MCard(content=serialize_term(term))
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def mcard_to_term(mcard: MCard) -> LambdaTerm:
|
|
144
|
+
"""Extract Lambda term from MCard"""
|
|
145
|
+
content = mcard.get_content(as_text=True)
|
|
146
|
+
return deserialize_term(content)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
150
|
+
# Collection Operations
|
|
151
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def store_term(collection: CardCollection, term: LambdaTerm) -> str:
|
|
155
|
+
"""Store a Lambda term in the collection and return its hash"""
|
|
156
|
+
mcard = term_to_mcard(term)
|
|
157
|
+
collection.add(mcard)
|
|
158
|
+
return mcard.hash
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def load_term(collection: CardCollection, hash_value: str) -> LambdaTerm | None:
|
|
162
|
+
"""Retrieve a Lambda term from the collection by hash"""
|
|
163
|
+
mcard = collection.get(hash_value)
|
|
164
|
+
if mcard is None:
|
|
165
|
+
return None
|
|
166
|
+
return mcard_to_term(mcard)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def term_exists(collection: CardCollection, hash_value: str) -> bool:
|
|
170
|
+
"""Check if a term exists in the collection"""
|
|
171
|
+
return collection.get(hash_value) is not None
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
175
|
+
# Pretty Printing
|
|
176
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def pretty_print_shallow(term: LambdaTerm) -> str:
|
|
180
|
+
"""Pretty-print a Lambda term (shallow - shows hashes for subterms)"""
|
|
181
|
+
if isinstance(term, VarTerm):
|
|
182
|
+
return term.name
|
|
183
|
+
elif isinstance(term, AbsTerm):
|
|
184
|
+
return f"λ{term.param}.〈{term.body[:8]}…〉"
|
|
185
|
+
elif isinstance(term, AppTerm):
|
|
186
|
+
return f"(〈{term.func[:8]}…〉 〈{term.arg[:8]}…〉)"
|
|
187
|
+
else:
|
|
188
|
+
return str(term)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def pretty_print_deep(collection: CardCollection, hash_value: str) -> str:
|
|
192
|
+
"""Pretty-print a Lambda term (deep - resolves all subterms from collection)"""
|
|
193
|
+
term = load_term(collection, hash_value)
|
|
194
|
+
if term is None:
|
|
195
|
+
return f"〈missing:{hash_value[:8]}…〉"
|
|
196
|
+
|
|
197
|
+
if isinstance(term, VarTerm):
|
|
198
|
+
return term.name
|
|
199
|
+
|
|
200
|
+
elif isinstance(term, AbsTerm):
|
|
201
|
+
body = pretty_print_deep(collection, term.body)
|
|
202
|
+
return f"(λ{term.param}.{body})"
|
|
203
|
+
|
|
204
|
+
elif isinstance(term, AppTerm):
|
|
205
|
+
func = pretty_print_deep(collection, term.func)
|
|
206
|
+
arg = pretty_print_deep(collection, term.arg)
|
|
207
|
+
return f"({func} {arg})"
|
|
208
|
+
|
|
209
|
+
else:
|
|
210
|
+
return str(term)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
214
|
+
# Type Guards
|
|
215
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def is_var(term: LambdaTerm) -> bool:
|
|
219
|
+
"""Check if term is a variable"""
|
|
220
|
+
return isinstance(term, VarTerm)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def is_abs(term: LambdaTerm) -> bool:
|
|
224
|
+
"""Check if term is an abstraction"""
|
|
225
|
+
return isinstance(term, AbsTerm)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def is_app(term: LambdaTerm) -> bool:
|
|
229
|
+
"""Check if term is an application"""
|
|
230
|
+
return isinstance(term, AppTerm)
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"""Layer 3 Satori Sheaf Cohomology & Multi-Agent Consensus Auditing (DEL-390-02, INV-390-02).
|
|
2
|
+
|
|
3
|
+
Implements Sheaf-theoretic multi-agent state consistency and Maxwell's Demon gating:
|
|
4
|
+
- Local sections s_i over open sets U_i must agree on intersections:
|
|
5
|
+
s_i|_{U_i ∩ U_j} == s_j|_{U_i ∩ U_j} ∀ i, j
|
|
6
|
+
- Vanishing first cohomology class H¹ = 0 guarantees zero conflict obstruction,
|
|
7
|
+
enabling unique global gluing into the SSOT state section.
|
|
8
|
+
- Maxwell's Demon (§3.2, INV-362-04): validates contributor DID grounding,
|
|
9
|
+
non-empty content, and zero synthetic hallucination markers.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import hashlib
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
16
|
+
|
|
17
|
+
from clm.layer3.satori.speech_act import encode_satori_binary
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class Place:
|
|
22
|
+
"""An open-set place identifier in a distributed topological space."""
|
|
23
|
+
id: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class Marking:
|
|
28
|
+
"""Maps token places / colors to their associated content hashes or values."""
|
|
29
|
+
tokens: Dict[str, List[str]] = field(default_factory=dict)
|
|
30
|
+
|
|
31
|
+
def with_token(self, place: str, val: str) -> Marking:
|
|
32
|
+
tokens = dict(self.tokens)
|
|
33
|
+
if place not in tokens:
|
|
34
|
+
tokens[place] = []
|
|
35
|
+
else:
|
|
36
|
+
tokens[place] = list(tokens[place])
|
|
37
|
+
tokens[place].append(val)
|
|
38
|
+
return Marking(tokens=tokens)
|
|
39
|
+
|
|
40
|
+
def restrict(self, places: Set[Place]) -> Marking:
|
|
41
|
+
"""Restrict marking to a subset of places."""
|
|
42
|
+
place_ids = {p.id for p in places}
|
|
43
|
+
restricted = {k: list(v) for k, v in self.tokens.items() if k in place_ids}
|
|
44
|
+
return Marking(tokens=restricted)
|
|
45
|
+
|
|
46
|
+
def to_digest(self) -> str:
|
|
47
|
+
items = sorted((k, sorted(v)) for k, v in self.tokens.items())
|
|
48
|
+
raw = str(items).encode("utf-8")
|
|
49
|
+
return hashlib.sha256(raw).hexdigest()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class OpenSet:
|
|
54
|
+
"""An open set consisting of a collection of discrete Places."""
|
|
55
|
+
places: frozenset[Place] = field(default_factory=frozenset)
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def from_ids(cls, *ids: str) -> OpenSet:
|
|
59
|
+
return cls(frozenset(Place(id=i) for i in ids))
|
|
60
|
+
|
|
61
|
+
def intersection(self, other: OpenSet) -> OpenSet:
|
|
62
|
+
return OpenSet(self.places.intersection(other.places))
|
|
63
|
+
|
|
64
|
+
def union(self, other: OpenSet) -> OpenSet:
|
|
65
|
+
return OpenSet(self.places.union(other.places))
|
|
66
|
+
|
|
67
|
+
def is_empty(self) -> bool:
|
|
68
|
+
return len(self.places) == 0
|
|
69
|
+
|
|
70
|
+
def is_subset(self, other: OpenSet) -> bool:
|
|
71
|
+
return self.places.issubset(other.places)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class Section:
|
|
76
|
+
"""A local section pairing an open set cover with a state marking."""
|
|
77
|
+
open_set: OpenSet
|
|
78
|
+
marking: Marking
|
|
79
|
+
|
|
80
|
+
def restrict(self, subset: OpenSet) -> Section:
|
|
81
|
+
if not subset.is_subset(self.open_set):
|
|
82
|
+
raise ValueError("Cannot restrict section to non-subset open set")
|
|
83
|
+
return Section(open_set=subset, marking=self.marking.restrict(set(subset.places)))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass
|
|
87
|
+
class SheafAuditReport:
|
|
88
|
+
"""Outcome of a sheaf consensus audit evaluating the H¹ = 0 condition."""
|
|
89
|
+
h1_vanishes: bool
|
|
90
|
+
cohomology_h1: int
|
|
91
|
+
obstructions: List[str]
|
|
92
|
+
global_section: Optional[Section] = None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class Sheaf:
|
|
96
|
+
"""Sheaf engine verifying the gluing axiom on open covers."""
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def gluing_check(sections: List[Section], open_cover: List[OpenSet]) -> Tuple[Optional[Section], List[str]]:
|
|
100
|
+
"""Verifies that local sections agree on all pairwise intersections.
|
|
101
|
+
Returns:
|
|
102
|
+
(global_section, []) if H¹ = 0 holds.
|
|
103
|
+
(None, [obstruction_reasons...]) if H¹ != 0 (obstruction detected).
|
|
104
|
+
"""
|
|
105
|
+
if len(sections) != len(open_cover):
|
|
106
|
+
return None, ["Input length mismatch between sections and open cover"]
|
|
107
|
+
|
|
108
|
+
if not sections:
|
|
109
|
+
return Section(open_set=OpenSet(), marking=Marking()), []
|
|
110
|
+
|
|
111
|
+
obstructions: List[str] = []
|
|
112
|
+
n = len(sections)
|
|
113
|
+
|
|
114
|
+
for i in range(n):
|
|
115
|
+
for j in range(i + 1, n):
|
|
116
|
+
u_ij = open_cover[i].intersection(open_cover[j])
|
|
117
|
+
if u_ij.is_empty():
|
|
118
|
+
continue
|
|
119
|
+
|
|
120
|
+
sec_i_res = sections[i].restrict(u_ij)
|
|
121
|
+
sec_j_res = sections[j].restrict(u_ij)
|
|
122
|
+
|
|
123
|
+
if sec_i_res.marking.to_digest() != sec_j_res.marking.to_digest():
|
|
124
|
+
obstructions.append(
|
|
125
|
+
f"Cohomology class H¹ != 0 obstruction on overlap {sorted(p.id for p in u_ij.places)}: "
|
|
126
|
+
f"Section {i} digest {sec_i_res.marking.to_digest()[:8]} != Section {j} digest {sec_j_res.marking.to_digest()[:8]}"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
if obstructions:
|
|
130
|
+
return None, obstructions
|
|
131
|
+
|
|
132
|
+
# Glue into unified global section
|
|
133
|
+
all_places = set()
|
|
134
|
+
merged_tokens: Dict[str, List[str]] = {}
|
|
135
|
+
for s in sections:
|
|
136
|
+
all_places.update(s.open_set.places)
|
|
137
|
+
for k, v in s.marking.tokens.items():
|
|
138
|
+
if k not in merged_tokens:
|
|
139
|
+
merged_tokens[k] = list(v)
|
|
140
|
+
|
|
141
|
+
global_sec = Section(open_set=OpenSet(frozenset(all_places)), marking=Marking(tokens=merged_tokens))
|
|
142
|
+
return global_sec, []
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class SheafAuditor:
|
|
146
|
+
"""Auditor for multi-agent distributed consensus."""
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
def audit_consensus(
|
|
150
|
+
cls,
|
|
151
|
+
sections: List[Section],
|
|
152
|
+
open_cover: Optional[List[OpenSet]] = None,
|
|
153
|
+
) -> SheafAuditReport:
|
|
154
|
+
"""Audit pairwise section agreement. Vanishing H¹ (cohomology_h1 = 0) indicates consensus."""
|
|
155
|
+
if open_cover is None:
|
|
156
|
+
open_cover = [s.open_set for s in sections]
|
|
157
|
+
|
|
158
|
+
global_sec, obstructions = Sheaf.gluing_check(sections, open_cover)
|
|
159
|
+
if obstructions:
|
|
160
|
+
return SheafAuditReport(
|
|
161
|
+
h1_vanishes=False,
|
|
162
|
+
cohomology_h1=1,
|
|
163
|
+
obstructions=obstructions,
|
|
164
|
+
global_section=None,
|
|
165
|
+
)
|
|
166
|
+
return SheafAuditReport(
|
|
167
|
+
h1_vanishes=True,
|
|
168
|
+
cohomology_h1=0,
|
|
169
|
+
obstructions=[],
|
|
170
|
+
global_section=global_sec,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
@classmethod
|
|
174
|
+
def audit_partitions(
|
|
175
|
+
cls,
|
|
176
|
+
partitions: List[Dict[str, Any]],
|
|
177
|
+
shared_keys: Optional[Set[str]] = None,
|
|
178
|
+
) -> SheafAuditReport:
|
|
179
|
+
"""Audit distributed agent state partition dictionaries.
|
|
180
|
+
Each partition has a 'did', 'places' (keys), and 'state' (mapping).
|
|
181
|
+
"""
|
|
182
|
+
sections: List[Section] = []
|
|
183
|
+
covers: List[OpenSet] = []
|
|
184
|
+
|
|
185
|
+
for p in partitions:
|
|
186
|
+
keys = set(p.get("places", p.get("state", {}).keys()))
|
|
187
|
+
open_set = OpenSet.from_ids(*keys)
|
|
188
|
+
tokens = {}
|
|
189
|
+
for k, v in p.get("state", {}).items():
|
|
190
|
+
tokens[k] = [str(v)] if not isinstance(v, list) else [str(x) for x in v]
|
|
191
|
+
sections.append(Section(open_set=open_set, marking=Marking(tokens=tokens)))
|
|
192
|
+
covers.append(open_set)
|
|
193
|
+
|
|
194
|
+
return cls.audit_consensus(sections, covers)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def audit_maxwell_demon(node: Dict[str, Any]) -> Dict[str, Any]:
|
|
198
|
+
"""Audits a Satori message speech act via Maxwell's Demon (§3.2, INV-362-04).
|
|
199
|
+
Validates DID grounding, non-empty content, and absence of synthetic hallucination markers.
|
|
200
|
+
Returns receipt dict with 'verified', 'cohomology_h1', 'lagrangian_delta', 'hash', 'rejection_reason'.
|
|
201
|
+
"""
|
|
202
|
+
encoded = encode_satori_binary(node)
|
|
203
|
+
msg_hash = hashlib.sha256(encoded).hexdigest()
|
|
204
|
+
|
|
205
|
+
user_did = node.get("user_did", "")
|
|
206
|
+
if not isinstance(user_did, str) or not user_did.startswith("did:"):
|
|
207
|
+
return {
|
|
208
|
+
"verified": False,
|
|
209
|
+
"cohomology_h1": 1,
|
|
210
|
+
"lagrangian_delta": -1,
|
|
211
|
+
"hash": msg_hash,
|
|
212
|
+
"rejection_reason": f"Cohomology Class H^1 != 0: Un-grounded DID contributor identity '{user_did}'",
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
children = node.get("elements", node.get("children", []))
|
|
216
|
+
if not children:
|
|
217
|
+
return {
|
|
218
|
+
"verified": False,
|
|
219
|
+
"cohomology_h1": 1,
|
|
220
|
+
"lagrangian_delta": -1,
|
|
221
|
+
"hash": msg_hash,
|
|
222
|
+
"rejection_reason": "Cohomology Class H^1 != 0: Empty message section cannot glue into Data Harness",
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
def _has_hallucination(n: Dict[str, Any]) -> bool:
|
|
226
|
+
txt = str(n.get("text", ""))
|
|
227
|
+
if "[HALLUCINATED]" in txt or "<hallucination>" in txt:
|
|
228
|
+
return True
|
|
229
|
+
for c in n.get("elements", n.get("children", [])):
|
|
230
|
+
if _has_hallucination(c):
|
|
231
|
+
return True
|
|
232
|
+
return False
|
|
233
|
+
|
|
234
|
+
if _has_hallucination(node):
|
|
235
|
+
return {
|
|
236
|
+
"verified": False,
|
|
237
|
+
"cohomology_h1": 1,
|
|
238
|
+
"lagrangian_delta": -1,
|
|
239
|
+
"hash": msg_hash,
|
|
240
|
+
"rejection_reason": "Cohomology Class H^1 != 0: Detected ungrounded hallucinated tokens in execution section",
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
"verified": True,
|
|
245
|
+
"cohomology_h1": 0,
|
|
246
|
+
"lagrangian_delta": 1,
|
|
247
|
+
"hash": msg_hash,
|
|
248
|
+
"rejection_reason": None,
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
__all__ = [
|
|
253
|
+
"Place",
|
|
254
|
+
"Marking",
|
|
255
|
+
"OpenSet",
|
|
256
|
+
"Section",
|
|
257
|
+
"Sheaf",
|
|
258
|
+
"SheafAuditReport",
|
|
259
|
+
"SheafAuditor",
|
|
260
|
+
"audit_maxwell_demon",
|
|
261
|
+
]
|