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
clm/layer0/model/card.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from clm.layer0.model.g_time import GTime
|
|
4
|
+
from clm.layer0.model.hash.validator import HashAlgorithm, HashValidator
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MCard:
|
|
8
|
+
"""MCard - Content-addressable data container (Data Plane).
|
|
9
|
+
|
|
10
|
+
DOTS Vocabulary Role: CARRIER
|
|
11
|
+
=============================
|
|
12
|
+
|
|
13
|
+
MCard is the **Carrier** in the Double Operadic Theory of Systems (DOTS).
|
|
14
|
+
- Each MCard is an **Object** in the Carrier category Car(S)
|
|
15
|
+
- Hash-links between MCards are **Morphisms** in Car(S)
|
|
16
|
+
- The Carrier is the category of all actual data/systems
|
|
17
|
+
|
|
18
|
+
EOS Role: Invariant Content (Galois Root)
|
|
19
|
+
=========================================
|
|
20
|
+
|
|
21
|
+
MCard provides the **Invariant Substrate** in Experimental-Operational Symmetry:
|
|
22
|
+
- `Hash(Content)` is a **pure function** with no side effects
|
|
23
|
+
- Same content in Dev = Same hash in Prod (environment-invariant)
|
|
24
|
+
- This is the "Joint Reality" P(H,E) = P(E,H) in Bayesian terms
|
|
25
|
+
|
|
26
|
+
MVP Cards Architecture: Data Plane
|
|
27
|
+
===================================
|
|
28
|
+
|
|
29
|
+
::
|
|
30
|
+
|
|
31
|
+
┌───────────────────────────────────────────────────────┐
|
|
32
|
+
│ APPLICATION PLANE (VCard) │
|
|
33
|
+
│ Value Exchange / AuthN/AuthZ / Sovereign Memory │
|
|
34
|
+
└─────────────────────────┬─────────────────────────────┘
|
|
35
|
+
│ (Policy Triggers)
|
|
36
|
+
┌─────────────────────────▼─────────────────────────────┐
|
|
37
|
+
│ CONTROL PLANE (PCard) │
|
|
38
|
+
│ Polynomial Functor Composition / Monadic Execution │
|
|
39
|
+
└─────────────────────────┬─────────────────────────────┘
|
|
40
|
+
│ (Hash References)
|
|
41
|
+
┌─────────────────────────▼─────────────────────────────┐
|
|
42
|
+
│ DATA PLANE (MCard) ◀── YOU ARE HERE │
|
|
43
|
+
│ Immutable, Content-Addressable Storage / Monad │
|
|
44
|
+
└───────────────────────────────────────────────────────┘
|
|
45
|
+
|
|
46
|
+
The Empty Schema Principle
|
|
47
|
+
==========================
|
|
48
|
+
|
|
49
|
+
MCard embodies the Empty Schema Principle from the Wordless Book:
|
|
50
|
+
- Schema contains NO domain-specific terms (only hash, content, g_time)
|
|
51
|
+
- Domain customization happens via data (INSERT), not schema changes
|
|
52
|
+
- Universal applicability: same structure for ANY domain
|
|
53
|
+
|
|
54
|
+
Functional Requirements (from design docs)
|
|
55
|
+
==========================================
|
|
56
|
+
|
|
57
|
+
+--------+--------------------------------+----------------------------------+
|
|
58
|
+
| ID | Requirement | Implementation |
|
|
59
|
+
+--------+--------------------------------+----------------------------------+
|
|
60
|
+
| M-1 | Content-addressable via hash | self.hash = SHA-256(content) |
|
|
61
|
+
| M-2 | CRD-only (no UPDATE) | Immutable, no __setattr__ |
|
|
62
|
+
| M-3 | Include g_time for ordering | self.g_time field |
|
|
63
|
+
| M-4 | Human-readable content | get_content(as_text=True) |
|
|
64
|
+
| EOS-M1 | Hash is pure function | No side effects in hash compute |
|
|
65
|
+
| EOS-M2 | Content is immutable | Content set once in __init__ |
|
|
66
|
+
+--------+--------------------------------+----------------------------------+
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
content (bytes): Raw bytes of the content (Carrier Object data)
|
|
70
|
+
hash (str): SHA-256 cryptographic hash (Carrier Object identity)
|
|
71
|
+
g_time (str): Global timestamp with algorithm identifier
|
|
72
|
+
hash_function (HashAlgorithm): The hash algorithm used
|
|
73
|
+
|
|
74
|
+
See Also:
|
|
75
|
+
- docs/WorkingNotes/Permanent/Projects/PKC Kernel/MCard.md
|
|
76
|
+
- docs/WorkingNotes/Hub/Theory/Integration/DOTS Vocabulary as Efficient Representation for ABC Curriculum.md
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def __init__(
|
|
80
|
+
self,
|
|
81
|
+
content: str | bytes,
|
|
82
|
+
hash_function: str | HashAlgorithm = HashAlgorithm.get_default(),
|
|
83
|
+
):
|
|
84
|
+
"""Initialize an MCard with content.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
content: The content to store. Can be string or bytes.
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
ValueError: If content is None or empty
|
|
91
|
+
"""
|
|
92
|
+
if content is None:
|
|
93
|
+
raise ValueError("Content cannot be None")
|
|
94
|
+
|
|
95
|
+
if hash_function is None:
|
|
96
|
+
raise ValueError("hash_function cannot be None")
|
|
97
|
+
|
|
98
|
+
if isinstance(content, str | bytes) and len(content) == 0:
|
|
99
|
+
raise ValueError("Content cannot be empty")
|
|
100
|
+
|
|
101
|
+
self.content = (
|
|
102
|
+
content if isinstance(content, bytes) else content.encode("utf-8")
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
self.hash_function = HashAlgorithm(hash_function)
|
|
106
|
+
|
|
107
|
+
# Compute and log the hash
|
|
108
|
+
self.hash = HashValidator.compute_hash(content, self.hash_function)
|
|
109
|
+
logging.debug(f"Computed hash for content: {self.hash}")
|
|
110
|
+
|
|
111
|
+
self.g_time = GTime.stamp_now(self.hash_function)
|
|
112
|
+
|
|
113
|
+
# Cache the content type
|
|
114
|
+
from clm.layer0.model.interpreter import get_interpreter
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
self._content_type, _ = get_interpreter().detect_content_type(self.content)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
logging.warning(f"Failed to detect content type: {e}")
|
|
120
|
+
self._content_type = "unknown"
|
|
121
|
+
|
|
122
|
+
def get_content(self, as_text: bool = False) -> bytes | str:
|
|
123
|
+
"""Get the content.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
as_text: If True, returns the content as a string (decoded from UTF-8).
|
|
127
|
+
If False (default), returns raw bytes.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
The content as either bytes (default) or string, depending on the as_text parameter.
|
|
131
|
+
"""
|
|
132
|
+
if as_text:
|
|
133
|
+
try:
|
|
134
|
+
return self.content.decode("utf-8")
|
|
135
|
+
except UnicodeDecodeError:
|
|
136
|
+
# Return a string representation of the bytes if UTF-8 decoding fails
|
|
137
|
+
return f"<binary data, length={len(self.content)}>"
|
|
138
|
+
return self.content
|
|
139
|
+
|
|
140
|
+
def __repr__(self) -> str:
|
|
141
|
+
hash_short = self.hash[:12] if self.hash else "None"
|
|
142
|
+
return f"MCard(hash={hash_short!r}…, content_type={self._content_type!r})"
|
|
143
|
+
|
|
144
|
+
def __eq__(self, other: object) -> bool:
|
|
145
|
+
if not isinstance(other, MCard):
|
|
146
|
+
return NotImplemented
|
|
147
|
+
return self.hash == other.hash
|
|
148
|
+
|
|
149
|
+
def __hash__(self) -> int:
|
|
150
|
+
return hash(self.hash)
|
|
151
|
+
|
|
152
|
+
def get_hash(self) -> str:
|
|
153
|
+
"""Compute and return the hash of the content."""
|
|
154
|
+
return self.hash
|
|
155
|
+
|
|
156
|
+
def get_g_time(self) -> str:
|
|
157
|
+
"""Get the current GTime string computed from the current time."""
|
|
158
|
+
return self.g_time
|
|
159
|
+
|
|
160
|
+
def get_content_type(self):
|
|
161
|
+
"""Get the content type of the MCard content."""
|
|
162
|
+
return self._content_type
|
|
163
|
+
|
|
164
|
+
def to_dict(self):
|
|
165
|
+
"""Convert the MCard to a dictionary.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
dict: A dictionary representation of the MCard with content as string.
|
|
169
|
+
"""
|
|
170
|
+
content = self.get_content()
|
|
171
|
+
if isinstance(content, str):
|
|
172
|
+
# Content is already decoded string
|
|
173
|
+
content_str = content
|
|
174
|
+
elif isinstance(content, bytes):
|
|
175
|
+
try:
|
|
176
|
+
# Attempt decoding, but keep original bytes if fails
|
|
177
|
+
content_str = content.decode("utf-8")
|
|
178
|
+
except UnicodeDecodeError:
|
|
179
|
+
content_str = f"<binary data, length={len(content)}>"
|
|
180
|
+
else:
|
|
181
|
+
content_str = str(content)
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
"content": content_str,
|
|
185
|
+
"hash": self.get_hash(),
|
|
186
|
+
"g_time": self.get_g_time(),
|
|
187
|
+
"content_type": self.get_content_type(),
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
def to_display_dict(self) -> dict[str, str]:
|
|
191
|
+
"""Convert the MCard to a display-friendly dictionary.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
dict: A dictionary with formatted fields for display:
|
|
195
|
+
- hash: The card's unique hash
|
|
196
|
+
- content_type: The type of content in the card
|
|
197
|
+
- created_at: Formatted creation timestamp
|
|
198
|
+
- content_preview: A preview of the card's content (first 50 chars)
|
|
199
|
+
- card_class: The class name of the card (for debugging)
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
# Get content safely
|
|
203
|
+
content = self.get_content()
|
|
204
|
+
# Ensure we have a string for preview
|
|
205
|
+
if isinstance(content, str):
|
|
206
|
+
content_str = content
|
|
207
|
+
else:
|
|
208
|
+
content_str = str(content)
|
|
209
|
+
|
|
210
|
+
# Create preview
|
|
211
|
+
content_preview = content_str[:50] + (
|
|
212
|
+
"..." if len(content_str) > 50 else ""
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Format timestamp
|
|
216
|
+
created_at = self.get_g_time()
|
|
217
|
+
created_at_str = str(created_at)[:19] if created_at else "N/A"
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
"hash": self.get_hash(),
|
|
221
|
+
"content_type": self.get_content_type() or "unknown",
|
|
222
|
+
"created_at": created_at_str,
|
|
223
|
+
"content_preview": content_preview,
|
|
224
|
+
"card_class": self.__class__.__name__,
|
|
225
|
+
}
|
|
226
|
+
except (AttributeError, TypeError, ValueError) as e:
|
|
227
|
+
logging.error(f"Error processing card for display: {e}")
|
|
228
|
+
return {}
|
|
229
|
+
|
|
230
|
+
def get_dots_metadata(
|
|
231
|
+
self, tight_refs: list[str] = None, loose_refs: list[str] = None
|
|
232
|
+
):
|
|
233
|
+
"""Get DOTS vocabulary metadata for this MCard.
|
|
234
|
+
|
|
235
|
+
Returns the DOTS role information that positions this MCard
|
|
236
|
+
in the Double Operadic Theory of Systems framework.
|
|
237
|
+
|
|
238
|
+
MCard is always a CARRIER object in the Data Plane.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
tight_refs: Optional list of prerequisite MCard hashes (vertical composition)
|
|
242
|
+
loose_refs: Optional list of alternative MCard hashes (horizontal composition)
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
DOTSMetadata describing this card's role.
|
|
246
|
+
"""
|
|
247
|
+
from clm.layer0.model.dots import create_mcard_dots_metadata
|
|
248
|
+
|
|
249
|
+
return create_mcard_dots_metadata(tight_refs, loose_refs)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
class MCardFromData(MCard):
|
|
253
|
+
"""An MCard subclass that initializes from existing hash and g_time."""
|
|
254
|
+
|
|
255
|
+
def __init__(self, content: bytes, hash_value: str, g_time_str: str):
|
|
256
|
+
"""Initialize an MCard from pre-existing hash and g_time."""
|
|
257
|
+
if not isinstance(content, bytes):
|
|
258
|
+
raise TypeError(
|
|
259
|
+
"Content must be bytes when initializing from existing data."
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
if not hash_value:
|
|
263
|
+
raise ValueError("Hash value cannot be None or empty")
|
|
264
|
+
|
|
265
|
+
if not g_time_str:
|
|
266
|
+
raise ValueError("g_time string cannot be None or empty")
|
|
267
|
+
|
|
268
|
+
self.content = content
|
|
269
|
+
self.hash = hash_value
|
|
270
|
+
self.g_time = g_time_str # Directly assign the provided g_time string
|
|
271
|
+
self.hash_function = GTime.get_hash_function(self.g_time)
|
|
272
|
+
|
|
273
|
+
# Cache the content type
|
|
274
|
+
from clm.layer0.model.interpreter import get_interpreter
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
self._content_type, _ = get_interpreter().detect_content_type(self.content)
|
|
278
|
+
except Exception as e:
|
|
279
|
+
logging.warning(f"Failed to detect content type for MCardFromData: {e}")
|
|
280
|
+
self._content_type = "unknown"
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
"""Card Triad Grounding in Layer 0 (Sprint 384 / DEL-384-01).
|
|
2
|
+
|
|
3
|
+
Implements the irreducible computational foundation of the CLM OS kernel:
|
|
4
|
+
- MCard: Σ-type (Data, Content-Addressed Identity, Value constant 1 -> X)
|
|
5
|
+
- PCard: Π-type (Process, Dynamic Operator A -> B)
|
|
6
|
+
- VCard: Id-type (Witness, Gating Commits X -> 2 / Boolean PCard)
|
|
7
|
+
|
|
8
|
+
Conforms to:
|
|
9
|
+
- docs/spec/20-architecture/card-triad-architecture.md
|
|
10
|
+
- Leibnizian Monadology & Function-Number Duality
|
|
11
|
+
- Empty Schema Principle & Parameterized Content Hashing
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
from enum import Enum
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
21
|
+
|
|
22
|
+
from clm.cross_cutting.domain_types import (
|
|
23
|
+
AgentDid,
|
|
24
|
+
ContentHash,
|
|
25
|
+
HandleName,
|
|
26
|
+
MarkingHash,
|
|
27
|
+
PlaceId,
|
|
28
|
+
TransitionId,
|
|
29
|
+
make_agent_did,
|
|
30
|
+
make_content_hash,
|
|
31
|
+
make_handle_name,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def compute_canonical_serialized(payload: Any) -> str:
|
|
36
|
+
"""Serialize payload to deterministic canonical JSON (sorted keys, compact separators, UTF-8 preserved)."""
|
|
37
|
+
return json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def compute_canonical_hash(payload: Any) -> str:
|
|
41
|
+
"""Compute deterministic BLAKE3 content hash over canonical JSON preimage."""
|
|
42
|
+
from clm.layer0.utils import clm_hash_string
|
|
43
|
+
|
|
44
|
+
serialized = compute_canonical_serialized(payload)
|
|
45
|
+
return clm_hash_string(serialized)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# Core Triad: MCard (Σ-type)
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class MCard(BaseModel):
|
|
54
|
+
"""Universal immutable data entity and file system primitive (Σ-type / Carrier).
|
|
55
|
+
|
|
56
|
+
Normative Reference:
|
|
57
|
+
docs/spec/20-architecture/card-triad-architecture.md § 1.1 (Universal MCard Ontology)
|
|
58
|
+
docs/spec/20-architecture/system-architecture.md § 1.1 (Everything is an MCard)
|
|
59
|
+
|
|
60
|
+
Invariants:
|
|
61
|
+
INV-01 (Stateless Kenotic Purity): Zero disk writes or network access.
|
|
62
|
+
INV-09 (Cryptographic Content Addressing): Hash uniquely determines identity.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
|
|
66
|
+
|
|
67
|
+
uri: str = ""
|
|
68
|
+
hash: ContentHash = Field(default=ContentHash(""))
|
|
69
|
+
payload: Any = None
|
|
70
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
71
|
+
author: AgentDid = Field(default=AgentDid("did:clm:system"))
|
|
72
|
+
sequence: int = 1
|
|
73
|
+
|
|
74
|
+
def __init__(self, content: Any = None, **kwargs: Any) -> None:
|
|
75
|
+
"""Allow positional content MCard(content) or keyword initialization."""
|
|
76
|
+
if content is not None and not kwargs:
|
|
77
|
+
if isinstance(content, (str, bytes)):
|
|
78
|
+
from clm.layer0.utils import clm_hash_string
|
|
79
|
+
|
|
80
|
+
text = content.decode("utf-8") if isinstance(content, bytes) else content
|
|
81
|
+
h = clm_hash_string(text)
|
|
82
|
+
super().__init__(
|
|
83
|
+
uri=f"mcard:{h[:16]}",
|
|
84
|
+
hash=ContentHash(h),
|
|
85
|
+
payload=content,
|
|
86
|
+
author=AgentDid("did:clm:system"),
|
|
87
|
+
sequence=1,
|
|
88
|
+
)
|
|
89
|
+
return
|
|
90
|
+
elif isinstance(content, dict):
|
|
91
|
+
digest = compute_canonical_hash(content)
|
|
92
|
+
super().__init__(
|
|
93
|
+
uri=f"mcard:{digest[:16]}",
|
|
94
|
+
hash=ContentHash(digest),
|
|
95
|
+
payload=content,
|
|
96
|
+
author=AgentDid("did:clm:system"),
|
|
97
|
+
sequence=1,
|
|
98
|
+
)
|
|
99
|
+
return
|
|
100
|
+
super().__init__(**kwargs)
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def create(
|
|
104
|
+
cls,
|
|
105
|
+
uri: str,
|
|
106
|
+
payload: Any,
|
|
107
|
+
author: AgentDid | str,
|
|
108
|
+
sequence: int = 1,
|
|
109
|
+
metadata: dict[str, Any] | None = None,
|
|
110
|
+
) -> MCard:
|
|
111
|
+
digest = compute_canonical_hash(payload)
|
|
112
|
+
return cls(
|
|
113
|
+
uri=uri,
|
|
114
|
+
hash=make_content_hash(digest),
|
|
115
|
+
payload=payload,
|
|
116
|
+
metadata=metadata or {},
|
|
117
|
+
author=make_agent_did(str(author)),
|
|
118
|
+
sequence=sequence,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def content(self) -> bytes | None:
|
|
123
|
+
"""Compatibility property for algebraic consumers."""
|
|
124
|
+
if isinstance(self.payload, bytes):
|
|
125
|
+
return self.payload
|
|
126
|
+
if isinstance(self.payload, str):
|
|
127
|
+
return self.payload.encode("utf-8")
|
|
128
|
+
if self.payload is not None:
|
|
129
|
+
return compute_canonical_serialized(self.payload).encode("utf-8")
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def g_time(self) -> str:
|
|
134
|
+
"""Temporal coordinate compatibility property."""
|
|
135
|
+
return self.metadata.get("g_time", "sha256|1970-01-01T00:00:00Z|UTC")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# ---------------------------------------------------------------------------
|
|
139
|
+
# Core Triad: PCard (Π-type)
|
|
140
|
+
# ---------------------------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class InvariantPhase(str, Enum):
|
|
144
|
+
Precondition = "precondition"
|
|
145
|
+
Postcondition = "postcondition"
|
|
146
|
+
LoopInvariant = "loop_invariant"
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class CordisCoeffects(BaseModel):
|
|
150
|
+
"""Declared coeffects (@Inject dependencies) for PCards."""
|
|
151
|
+
|
|
152
|
+
model_config = ConfigDict(frozen=True)
|
|
153
|
+
|
|
154
|
+
required_services: list[str] = Field(default_factory=list)
|
|
155
|
+
input_schema_uri: str | None = None
|
|
156
|
+
output_schema_uri: str | None = None
|
|
157
|
+
required_capabilities: list[str] = Field(default_factory=list)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class PrimitivePCard(BaseModel):
|
|
161
|
+
"""Zero-coeffect constant function: 1 -> X."""
|
|
162
|
+
|
|
163
|
+
model_config = ConfigDict(frozen=True)
|
|
164
|
+
|
|
165
|
+
mcard: MCard
|
|
166
|
+
|
|
167
|
+
def evaluate(self) -> MCard:
|
|
168
|
+
return self.mcard
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class DynamicPCard(BaseModel):
|
|
172
|
+
"""Dynamic effectful computation: A -> B."""
|
|
173
|
+
|
|
174
|
+
model_config = ConfigDict(frozen=True)
|
|
175
|
+
|
|
176
|
+
id: str
|
|
177
|
+
code_hash: ContentHash
|
|
178
|
+
source_uri: str
|
|
179
|
+
coeffects: CordisCoeffects = Field(default_factory=CordisCoeffects)
|
|
180
|
+
signature: str
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class BooleanPCard(BaseModel):
|
|
184
|
+
"""Boolean guard specialization returning Bool (X -> 2)."""
|
|
185
|
+
|
|
186
|
+
model_config = ConfigDict(frozen=True)
|
|
187
|
+
|
|
188
|
+
id: str
|
|
189
|
+
phase: InvariantPhase
|
|
190
|
+
expression: str
|
|
191
|
+
guarded_uri_pattern: str
|
|
192
|
+
coeffects: CordisCoeffects = Field(default_factory=CordisCoeffects)
|
|
193
|
+
|
|
194
|
+
def is_precondition(self) -> bool:
|
|
195
|
+
return self.phase == InvariantPhase.Precondition
|
|
196
|
+
|
|
197
|
+
def is_postcondition(self) -> bool:
|
|
198
|
+
return self.phase == InvariantPhase.Postcondition
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class PCardDefinition(BaseModel):
|
|
202
|
+
"""Tagged polymorphic PCard definition."""
|
|
203
|
+
|
|
204
|
+
model_config = ConfigDict(frozen=True)
|
|
205
|
+
|
|
206
|
+
pcard_type: str = Field(pattern=r"^(primitive|dynamic|boolean)$")
|
|
207
|
+
primitive: PrimitivePCard | None = None
|
|
208
|
+
dynamic: DynamicPCard | None = None
|
|
209
|
+
boolean: BooleanPCard | None = None
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class PCard(BaseModel):
|
|
213
|
+
"""PCard: Process / Dynamic Operator / Control Plane (Π-type).
|
|
214
|
+
|
|
215
|
+
Normative Reference:
|
|
216
|
+
docs/spec/20-architecture/card-triad-architecture.md § 1.1 (PCard & Lambda Abstractions)
|
|
217
|
+
docs/spec/40-behavior/baldwin_monadic_pcard_algebra.md
|
|
218
|
+
|
|
219
|
+
Invariants:
|
|
220
|
+
INV-02 (Function-Number Duality): Function ≅ Number†.
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
|
|
224
|
+
|
|
225
|
+
uri: str = ""
|
|
226
|
+
hash: ContentHash = Field(default=ContentHash(""))
|
|
227
|
+
pcard_type: str = "primitive"
|
|
228
|
+
definition: PCardDefinition | None = None
|
|
229
|
+
primitive: PrimitivePCard | None = None
|
|
230
|
+
dynamic: DynamicPCard | None = None
|
|
231
|
+
boolean: BooleanPCard | None = None
|
|
232
|
+
coeffects: CordisCoeffects = Field(default_factory=CordisCoeffects)
|
|
233
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
234
|
+
sequence: int = 1
|
|
235
|
+
|
|
236
|
+
def __init__(self, content: Any = None, **kwargs: Any) -> None:
|
|
237
|
+
if content is not None and not kwargs:
|
|
238
|
+
if isinstance(content, PrimitivePCard):
|
|
239
|
+
super().__init__(
|
|
240
|
+
uri=content.mcard.uri,
|
|
241
|
+
hash=content.mcard.hash,
|
|
242
|
+
pcard_type="primitive",
|
|
243
|
+
primitive=content,
|
|
244
|
+
)
|
|
245
|
+
return
|
|
246
|
+
if isinstance(content, (str, bytes, dict)):
|
|
247
|
+
m = MCard(content)
|
|
248
|
+
prim = PrimitivePCard(mcard=m)
|
|
249
|
+
super().__init__(
|
|
250
|
+
uri=m.uri,
|
|
251
|
+
hash=m.hash,
|
|
252
|
+
pcard_type="primitive",
|
|
253
|
+
primitive=prim,
|
|
254
|
+
)
|
|
255
|
+
return
|
|
256
|
+
super().__init__(**kwargs)
|
|
257
|
+
|
|
258
|
+
def evaluate(self) -> MCard:
|
|
259
|
+
"""Evaluate the PCard polynomial morphism."""
|
|
260
|
+
if self.primitive is not None:
|
|
261
|
+
return self.primitive.evaluate()
|
|
262
|
+
if self.definition is not None and self.definition.primitive is not None:
|
|
263
|
+
return self.definition.primitive.evaluate()
|
|
264
|
+
return MCard(uri=self.uri, hash=self.hash, payload=self.metadata)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
# ---------------------------------------------------------------------------
|
|
268
|
+
# Core Triad: VCard (Id-type)
|
|
269
|
+
# ---------------------------------------------------------------------------
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
class BailVerdict(BaseModel):
|
|
273
|
+
"""Verdict returned by invariant evaluation or speculative execution."""
|
|
274
|
+
|
|
275
|
+
model_config = ConfigDict(frozen=True)
|
|
276
|
+
|
|
277
|
+
passed: bool
|
|
278
|
+
reason: str = ""
|
|
279
|
+
invariant_code: str = ""
|
|
280
|
+
context_dump: dict[str, Any] = Field(default_factory=dict)
|
|
281
|
+
|
|
282
|
+
@classmethod
|
|
283
|
+
def pass_verdict(cls) -> BailVerdict:
|
|
284
|
+
return cls(passed=True)
|
|
285
|
+
|
|
286
|
+
@classmethod
|
|
287
|
+
def bail(
|
|
288
|
+
cls, reason: str, invariant_code: str = "", context_dump: dict[str, Any] | None = None
|
|
289
|
+
) -> BailVerdict:
|
|
290
|
+
return cls(
|
|
291
|
+
passed=False,
|
|
292
|
+
reason=reason,
|
|
293
|
+
invariant_code=invariant_code,
|
|
294
|
+
context_dump=context_dump or {},
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class VCard(BaseModel):
|
|
299
|
+
"""VCard: Invariant Verification Witness & Gating Primitive (Id-type).
|
|
300
|
+
|
|
301
|
+
Normative Reference:
|
|
302
|
+
docs/spec/20-architecture/card-triad-architecture.md § 1.1 (VCard as Boolean PCard X -> 2)
|
|
303
|
+
docs/spec/40-behavior/hoare_triple_composition_protocol.md
|
|
304
|
+
|
|
305
|
+
Invariants:
|
|
306
|
+
INV-03 (Hoare Sandwich): {V_pre} Action {V_post} with <1ms atomic rollback.
|
|
307
|
+
|
|
308
|
+
All VCards are implemented as a special kind of PCard that returns Bool as its outcome
|
|
309
|
+
(X -> 2 = {true, false}), determining whether the runtime commits the state transition
|
|
310
|
+
or triggers an atomic rollback via Cordis Bail Dispatch.
|
|
311
|
+
"""
|
|
312
|
+
|
|
313
|
+
model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
|
|
314
|
+
|
|
315
|
+
uri: str = ""
|
|
316
|
+
hash: ContentHash = Field(default=ContentHash(""))
|
|
317
|
+
gate_type: str = "dispatch"
|
|
318
|
+
result: str = "pass"
|
|
319
|
+
verdict: BailVerdict = Field(default_factory=BailVerdict.pass_verdict)
|
|
320
|
+
boolean_pcard: BooleanPCard | None = None
|
|
321
|
+
witness_proof: str | None = None
|
|
322
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
323
|
+
sequence: int = 1
|
|
324
|
+
|
|
325
|
+
def is_passed(self) -> bool:
|
|
326
|
+
return self.result == "pass" and self.verdict.passed
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
# ---------------------------------------------------------------------------
|
|
330
|
+
# Auxiliary Domain Models (Petri Net & Token Models)
|
|
331
|
+
# ---------------------------------------------------------------------------
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
class TokenModel(BaseModel):
|
|
335
|
+
"""Immutable Colored Petri Net token representation."""
|
|
336
|
+
|
|
337
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
338
|
+
|
|
339
|
+
color: ContentHash = Field(description="Content hash representing token data")
|
|
340
|
+
carrier: str | None = Field(default=None, description="Carrier identifier for token routing")
|
|
341
|
+
timestamp: str | None = Field(default=None, description="ISO-8601 creation timestamp")
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class PlaceModel(BaseModel):
|
|
345
|
+
"""Immutable Petri Net place specification."""
|
|
346
|
+
|
|
347
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
348
|
+
|
|
349
|
+
id: PlaceId
|
|
350
|
+
name: str = Field(description="Human-readable place name")
|
|
351
|
+
tokens: int = Field(default=0, ge=0, description="Non-negative token count")
|
|
352
|
+
current_color: ContentHash | None = Field(default=None, description="Active color if token present")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
class TransitionModel(BaseModel):
|
|
356
|
+
"""Immutable Petri Net transition specification."""
|
|
357
|
+
|
|
358
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
359
|
+
|
|
360
|
+
id: TransitionId
|
|
361
|
+
name: str
|
|
362
|
+
inputs: list[PlaceId] = Field(default_factory=list)
|
|
363
|
+
outputs: list[PlaceId] = Field(default_factory=list)
|
|
364
|
+
condition: str | None = None
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
class MarkingModel(BaseModel):
|
|
368
|
+
"""Immutable Colored Petri Net marking state with bitemporal provenance."""
|
|
369
|
+
|
|
370
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
371
|
+
|
|
372
|
+
topology_hash: ContentHash
|
|
373
|
+
places: dict[PlaceId, int] = Field(default_factory=dict)
|
|
374
|
+
place_colors: dict[PlaceId, ContentHash] = Field(default_factory=dict)
|
|
375
|
+
parent_hash: ContentHash | None = None
|
|
376
|
+
fired_transition: TransitionId | None = None
|
|
377
|
+
sponsor_did: AgentDid
|
|
378
|
+
firer_did: AgentDid
|
|
379
|
+
|
|
380
|
+
@field_validator("sponsor_did", "firer_did")
|
|
381
|
+
@classmethod
|
|
382
|
+
def validate_did_prefix(cls, v: AgentDid) -> AgentDid:
|
|
383
|
+
if not str(v).startswith("did:"):
|
|
384
|
+
raise ValueError(f"Agent DID must start with 'did:', got '{v}'")
|
|
385
|
+
return v
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class CardModel(BaseModel):
|
|
389
|
+
"""Content-addressed MCard/PCard/VCard domain model."""
|
|
390
|
+
|
|
391
|
+
model_config = ConfigDict(frozen=True)
|
|
392
|
+
|
|
393
|
+
hash: ContentHash
|
|
394
|
+
token_type: str = Field(pattern=r"^(mcard|pcard|vcard|token)$")
|
|
395
|
+
payload: dict[str, Any] = Field(default_factory=dict)
|
|
396
|
+
timestamp: str | None = None
|
|
397
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
__all__ = [
|
|
401
|
+
"AgentDid",
|
|
402
|
+
"BailVerdict",
|
|
403
|
+
"BooleanPCard",
|
|
404
|
+
"CardModel",
|
|
405
|
+
"ContentHash",
|
|
406
|
+
"CordisCoeffects",
|
|
407
|
+
"DynamicPCard",
|
|
408
|
+
"HandleName",
|
|
409
|
+
"InvariantPhase",
|
|
410
|
+
"MarkingHash",
|
|
411
|
+
"MarkingModel",
|
|
412
|
+
"MCard",
|
|
413
|
+
"PCard",
|
|
414
|
+
"PCardDefinition",
|
|
415
|
+
"PlaceId",
|
|
416
|
+
"PlaceModel",
|
|
417
|
+
"PrimitivePCard",
|
|
418
|
+
"TokenModel",
|
|
419
|
+
"TransitionId",
|
|
420
|
+
"TransitionModel",
|
|
421
|
+
"VCard",
|
|
422
|
+
"compute_canonical_hash",
|
|
423
|
+
"compute_canonical_serialized",
|
|
424
|
+
"make_agent_did",
|
|
425
|
+
"make_content_hash",
|
|
426
|
+
"make_handle_name",
|
|
427
|
+
]
|