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/layer4/api.py
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import uvicorn
|
|
2
|
+
from fastapi import FastAPI, File, Form, HTTPException, UploadFile
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from clm.cross_cutting.config.logging import (
|
|
6
|
+
SecurityAuditLogger,
|
|
7
|
+
get_logger,
|
|
8
|
+
setup_logging,
|
|
9
|
+
)
|
|
10
|
+
from clm.layer0.model.card import MCard
|
|
11
|
+
from clm.layer2.card_collection import CardCollection
|
|
12
|
+
|
|
13
|
+
# Configure logging
|
|
14
|
+
setup_logging()
|
|
15
|
+
logger = get_logger(__name__)
|
|
16
|
+
security_audit = SecurityAuditLogger()
|
|
17
|
+
|
|
18
|
+
# Initialize FastAPI app
|
|
19
|
+
app = FastAPI(
|
|
20
|
+
title="MCard API",
|
|
21
|
+
description="API for managing MCard content-addressable storage.",
|
|
22
|
+
version="1.0.0",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Initialize CardCollection. This will use the default database path.
|
|
26
|
+
try:
|
|
27
|
+
card_collection = CardCollection()
|
|
28
|
+
db_path = getattr(card_collection.engine, "db_path", "unknown")
|
|
29
|
+
logger.info(f"CardCollection initialized with DB at: {db_path}")
|
|
30
|
+
except Exception as e:
|
|
31
|
+
logger.critical(f"Failed to initialize CardCollection: {e}")
|
|
32
|
+
raise RuntimeError(f"Could not initialize database connection: {e}") from e
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@app.post("/content/cards", status_code=201)
|
|
36
|
+
async def store_content_card(
|
|
37
|
+
content: UploadFile = File(...),
|
|
38
|
+
metadata: str | None = Form(None), # Metadata sent as a JSON string
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
Store new content and create an MCard.
|
|
42
|
+
|
|
43
|
+
- **content**: The file content to be stored.
|
|
44
|
+
- **metadata**: Optional JSON string containing metadata.
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
# Read content from the uploaded file
|
|
48
|
+
file_content = await content.read()
|
|
49
|
+
if not file_content:
|
|
50
|
+
raise HTTPException(status_code=400, detail="Content cannot be empty.")
|
|
51
|
+
|
|
52
|
+
# Create an MCard instance
|
|
53
|
+
mcard = MCard(content=file_content)
|
|
54
|
+
|
|
55
|
+
# Add the card to the collection using a thread pool
|
|
56
|
+
import asyncio
|
|
57
|
+
|
|
58
|
+
card_hash = await asyncio.to_thread(card_collection.add, mcard)
|
|
59
|
+
|
|
60
|
+
# Retrieve the newly stored card to return its details
|
|
61
|
+
stored_card = await asyncio.to_thread(card_collection.get, mcard.get_hash())
|
|
62
|
+
if not stored_card:
|
|
63
|
+
raise HTTPException(
|
|
64
|
+
status_code=500, detail="Failed to retrieve card after adding."
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
response_data = {
|
|
68
|
+
"hash": stored_card.get_hash(),
|
|
69
|
+
"content_type": stored_card.get_content_type(),
|
|
70
|
+
"g_time": stored_card.get_g_time(),
|
|
71
|
+
"message": "Content stored successfully",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if card_hash != mcard.get_hash():
|
|
75
|
+
collision_msg = (
|
|
76
|
+
f"Content already exists or a hash collision occurred. "
|
|
77
|
+
f"Event card created with hash: {card_hash}"
|
|
78
|
+
)
|
|
79
|
+
response_data["message"] = collision_msg
|
|
80
|
+
response_data["event_hash"] = card_hash
|
|
81
|
+
|
|
82
|
+
return response_data
|
|
83
|
+
|
|
84
|
+
except HTTPException:
|
|
85
|
+
raise
|
|
86
|
+
except ValueError as e:
|
|
87
|
+
logger.warning(f"Validation error while creating card: {e}")
|
|
88
|
+
raise HTTPException(status_code=400, detail=str(e)) from e
|
|
89
|
+
except Exception as e:
|
|
90
|
+
logger.error(
|
|
91
|
+
f"An unexpected error occurred while storing content: {e}", exc_info=True
|
|
92
|
+
)
|
|
93
|
+
raise HTTPException(
|
|
94
|
+
status_code=500, detail="An internal server error occurred."
|
|
95
|
+
) from e
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# --- Pydantic Models for API Responses ---
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class CardResponse(BaseModel):
|
|
102
|
+
hash: str
|
|
103
|
+
content_type: str
|
|
104
|
+
g_time: str
|
|
105
|
+
metadata: dict | None = None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class PaginatedCardResponse(BaseModel):
|
|
109
|
+
items: list[CardResponse]
|
|
110
|
+
total_items: int
|
|
111
|
+
page_number: int
|
|
112
|
+
page_size: int
|
|
113
|
+
total_pages: int
|
|
114
|
+
has_next: bool
|
|
115
|
+
has_previous: bool
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@app.get("/content/cards", response_model=PaginatedCardResponse)
|
|
119
|
+
async def list_content_cards(
|
|
120
|
+
query: str | None = None, page: int = 1, page_size: int = 10
|
|
121
|
+
):
|
|
122
|
+
"""
|
|
123
|
+
List content cards with pagination and optional search.
|
|
124
|
+
|
|
125
|
+
- **query**: Optional search string to filter cards by content.
|
|
126
|
+
- **page**: The page number to retrieve.
|
|
127
|
+
- **page_size**: The number of items per page.
|
|
128
|
+
"""
|
|
129
|
+
try:
|
|
130
|
+
import asyncio
|
|
131
|
+
|
|
132
|
+
# Ensure await is used for asynchronous operations by threading sync operations
|
|
133
|
+
if query:
|
|
134
|
+
page_obj = await asyncio.to_thread(
|
|
135
|
+
card_collection.search_by_content,
|
|
136
|
+
search_string=query,
|
|
137
|
+
page_number=page,
|
|
138
|
+
page_size=page_size,
|
|
139
|
+
)
|
|
140
|
+
else:
|
|
141
|
+
page_obj = await asyncio.to_thread(
|
|
142
|
+
card_collection.get_page, page_number=page, page_size=page_size
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Convert MCard objects to a serializable format
|
|
146
|
+
response_items = [
|
|
147
|
+
CardResponse(
|
|
148
|
+
hash=card.get_hash(),
|
|
149
|
+
content_type=card.get_content_type(),
|
|
150
|
+
g_time=card.get_g_time(),
|
|
151
|
+
)
|
|
152
|
+
for card in page_obj.items
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
return PaginatedCardResponse(
|
|
156
|
+
items=response_items,
|
|
157
|
+
total_items=page_obj.total_items,
|
|
158
|
+
page_number=page_obj.page_number,
|
|
159
|
+
page_size=page_obj.page_size,
|
|
160
|
+
total_pages=page_obj.total_pages,
|
|
161
|
+
has_next=page_obj.has_next,
|
|
162
|
+
has_previous=page_obj.has_previous,
|
|
163
|
+
)
|
|
164
|
+
except HTTPException:
|
|
165
|
+
raise
|
|
166
|
+
except Exception as e:
|
|
167
|
+
logger.error(f"Error listing cards: {e}", exc_info=True)
|
|
168
|
+
raise HTTPException(
|
|
169
|
+
status_code=500, detail="An internal server error occurred."
|
|
170
|
+
) from e
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@app.get("/content/cards/{hash}", response_model=CardResponse)
|
|
174
|
+
async def get_content_card(hash: str):
|
|
175
|
+
"""
|
|
176
|
+
Retrieve a single content card by its hash.
|
|
177
|
+
|
|
178
|
+
- **hash**: The SHA-256 hash of the content card to retrieve.
|
|
179
|
+
"""
|
|
180
|
+
try:
|
|
181
|
+
import asyncio
|
|
182
|
+
|
|
183
|
+
# Ensure await is used via thread pool
|
|
184
|
+
card = await asyncio.to_thread(card_collection.get, hash)
|
|
185
|
+
if not card:
|
|
186
|
+
raise HTTPException(status_code=404, detail="Card not found.")
|
|
187
|
+
|
|
188
|
+
return CardResponse(
|
|
189
|
+
hash=card.get_hash(),
|
|
190
|
+
content_type=card.get_content_type(),
|
|
191
|
+
g_time=card.get_g_time(),
|
|
192
|
+
)
|
|
193
|
+
except HTTPException:
|
|
194
|
+
raise
|
|
195
|
+
except Exception as e:
|
|
196
|
+
logger.error(f"Error retrieving card {hash}: {e}", exc_info=True)
|
|
197
|
+
raise HTTPException(
|
|
198
|
+
status_code=500, detail="An internal server error occurred."
|
|
199
|
+
) from e
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@app.delete("/content/cards/{hash}", status_code=204)
|
|
203
|
+
async def delete_content_card(hash: str):
|
|
204
|
+
"""
|
|
205
|
+
Delete a content card by its hash.
|
|
206
|
+
|
|
207
|
+
- **hash**: The SHA-256 hash of the content card to delete.
|
|
208
|
+
"""
|
|
209
|
+
try:
|
|
210
|
+
import asyncio
|
|
211
|
+
|
|
212
|
+
# Ensure await is used via thread pool
|
|
213
|
+
success = await asyncio.to_thread(card_collection.delete, hash)
|
|
214
|
+
if not success:
|
|
215
|
+
raise HTTPException(
|
|
216
|
+
status_code=404, detail="Card not found or could not be deleted."
|
|
217
|
+
)
|
|
218
|
+
# Return None to produce a 204 No Content response
|
|
219
|
+
return None
|
|
220
|
+
except HTTPException:
|
|
221
|
+
raise
|
|
222
|
+
except Exception as e:
|
|
223
|
+
logger.error(f"Error deleting card {hash}: {e}", exc_info=True)
|
|
224
|
+
raise HTTPException(
|
|
225
|
+
status_code=500, detail="An internal server error occurred."
|
|
226
|
+
) from e
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def start_api_server():
|
|
230
|
+
"""Starts the Uvicorn server."""
|
|
231
|
+
logger.info("Starting MCard API server...")
|
|
232
|
+
uvicorn.run(app, host="0.0.0.0", port=28302, log_level="info") # nosec B104
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
if __name__ == "__main__":
|
|
236
|
+
start_api_server()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""MCard Bootstrap logic encapsulation.
|
|
2
|
+
|
|
3
|
+
Defines natively pure functionality previously housed implicitly in shell wrapper architecture.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from clm.layer4.bootstrap.bootstrapper import KernelBootstrapper
|
|
7
|
+
from clm.layer4.bootstrap.injection import SchemaInjector, compute_shannon_entropy
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"KernelBootstrapper",
|
|
11
|
+
"SchemaInjector",
|
|
12
|
+
"compute_shannon_entropy",
|
|
13
|
+
]
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Kernel Bootstrapper.
|
|
2
|
+
|
|
3
|
+
Enforces the Inception Constraint by deriving the initial system state and database
|
|
4
|
+
topology exclusively from the narrative architectural documentation rather than
|
|
5
|
+
hardcoded scripts.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import re
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import yaml
|
|
13
|
+
|
|
14
|
+
from clm.cross_cutting.config.config_constants import _PROJECT_ROOT, META_FUNCTIONALITY_DB_PATH
|
|
15
|
+
from clm.layer0.model.card import MCard
|
|
16
|
+
from clm.layer2.card_collection import CardCollection
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
ARCHITECTURE_DOC_PATH = _PROJECT_ROOT / "clm" / "seed_clm_playbook.yaml"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class KernelBootstrapper:
|
|
24
|
+
"""Parses architectural docs to bootstrap the Kenotic Root `meta_functionality.db`."""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
override_doc_path: Path | None = None,
|
|
29
|
+
override_db_path: Path | None = None,
|
|
30
|
+
) -> None:
|
|
31
|
+
self.doc_path = override_doc_path or ARCHITECTURE_DOC_PATH
|
|
32
|
+
self.db_path = override_db_path or META_FUNCTIONALITY_DB_PATH
|
|
33
|
+
|
|
34
|
+
def extract_yaml_clm(self) -> dict:
|
|
35
|
+
"""Parse the resource to extract the executable configuration.
|
|
36
|
+
|
|
37
|
+
If the file is a YAML file, parses directly. If markdown, extracts the last YAML block.
|
|
38
|
+
Raises ValueError if the YAML block is missing or malformed.
|
|
39
|
+
"""
|
|
40
|
+
if not self.doc_path.exists():
|
|
41
|
+
raise FileNotFoundError(
|
|
42
|
+
f"Architectural document not found: {self.doc_path}"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
content = self.doc_path.read_text("utf-8")
|
|
46
|
+
|
|
47
|
+
if self.doc_path.suffix in (".yaml", ".yml"):
|
|
48
|
+
try:
|
|
49
|
+
return yaml.safe_load(content)
|
|
50
|
+
except yaml.YAMLError as exc:
|
|
51
|
+
raise ValueError(f"Failed to parse CLM YAML file: {exc}") from exc
|
|
52
|
+
|
|
53
|
+
# We look for the final yaml block (after the "Executable Kernel Topology Map" header)
|
|
54
|
+
matches = list(re.finditer(r"```yaml(.*?)```", content, flags=re.DOTALL))
|
|
55
|
+
if not matches:
|
|
56
|
+
raise ValueError(
|
|
57
|
+
"No YAML configuration blocks found in the architecture document."
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Take the last YAML block assuming it's the Bootloader Map
|
|
61
|
+
yaml_str = matches[-1].group(1).strip()
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
return yaml.safe_load(yaml_str)
|
|
65
|
+
except yaml.YAMLError as exc:
|
|
66
|
+
raise ValueError(f"Failed to parse CLM YAML block: {exc}") from exc
|
|
67
|
+
|
|
68
|
+
def bootstrap(self) -> CardCollection:
|
|
69
|
+
"""Instantiate the Kenotic Root and provision foundational tables.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
CardCollection: The verified root collection pointing to the Mesh dependencies.
|
|
73
|
+
"""
|
|
74
|
+
clm = self.extract_yaml_clm().get("clm")
|
|
75
|
+
if not clm or "concrete_impl" not in clm:
|
|
76
|
+
raise ValueError(
|
|
77
|
+
"Malformed CLM: expected root 'clm' dict with 'concrete_impl'."
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
databases = clm["concrete_impl"].get("databases", {})
|
|
81
|
+
if not databases:
|
|
82
|
+
raise ValueError("No databases map defined in the executable topology.")
|
|
83
|
+
|
|
84
|
+
# We construct the meta_functionality.db
|
|
85
|
+
root_collection = CardCollection(db_path=str(self.db_path))
|
|
86
|
+
|
|
87
|
+
# 1. Store the CLM bootloader itself as the initial N_0 Generalized Number
|
|
88
|
+
boot_card = MCard(content=yaml.dump({"clm": clm}, sort_keys=False))
|
|
89
|
+
if not root_collection.get(boot_card.hash):
|
|
90
|
+
root_collection.add(boot_card)
|
|
91
|
+
|
|
92
|
+
# 2. Extract database topologies and register their Pointers mapping to the Project Root
|
|
93
|
+
for db_name, rel_path in databases.items():
|
|
94
|
+
handle_name = f"pkc://db/{db_name}"
|
|
95
|
+
# The PCard/Pointer simply stores JSON metadata about the path
|
|
96
|
+
pointer_card = MCard(
|
|
97
|
+
content=yaml.dump(
|
|
98
|
+
{
|
|
99
|
+
"path": str(_PROJECT_ROOT / rel_path),
|
|
100
|
+
"schema_version": "v1",
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
if not root_collection.resolve_handle(handle_name):
|
|
105
|
+
root_collection.add_with_handle(pointer_card, handle_name)
|
|
106
|
+
|
|
107
|
+
# 3. Simulate codebase hash (normally this would be git hash)
|
|
108
|
+
codebase_pointer = MCard(
|
|
109
|
+
content=yaml.dump({"source": "local", "commit": "HEAD"})
|
|
110
|
+
)
|
|
111
|
+
if not root_collection.resolve_handle("pkc://codebase/current"):
|
|
112
|
+
root_collection.add_with_handle(codebase_pointer, "pkc://codebase/current")
|
|
113
|
+
|
|
114
|
+
# 4. Bootstrap complete.
|
|
115
|
+
logger.info(
|
|
116
|
+
"KernelBootstrapper successfully instantiated meta_functionality.db."
|
|
117
|
+
)
|
|
118
|
+
return root_collection
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def execute(target_dir: str):
|
|
6
|
+
"""
|
|
7
|
+
Executes the Database Cleanup Execution dynamically.
|
|
8
|
+
"""
|
|
9
|
+
try:
|
|
10
|
+
from clm.layer0.loader import CLMChapterLoader
|
|
11
|
+
except ImportError:
|
|
12
|
+
print(
|
|
13
|
+
"[CLEANUP] Critical Error: clm core modules not detected. Ensure uv dependencies are synchronized."
|
|
14
|
+
)
|
|
15
|
+
sys.exit(1)
|
|
16
|
+
|
|
17
|
+
from clm.cross_cutting.config.settings import settings
|
|
18
|
+
|
|
19
|
+
bs_dir = Path(target_dir)
|
|
20
|
+
db_path = bs_dir / settings.bootstrap.db_dir
|
|
21
|
+
|
|
22
|
+
yaml_path = (
|
|
23
|
+
bs_dir / settings.bootstrap.manifests_dir / settings.bootstrap.cleanup_manifest
|
|
24
|
+
)
|
|
25
|
+
if not yaml_path.exists():
|
|
26
|
+
print(f"[CLEANUP] Critical Error: Cleanup schematic missing at {yaml_path}")
|
|
27
|
+
sys.exit(1)
|
|
28
|
+
|
|
29
|
+
chapter = CLMChapterLoader.load_from_yaml(str(yaml_path))
|
|
30
|
+
|
|
31
|
+
from clm.layer4.bootstrap.clm_hooks import execute_cleanup
|
|
32
|
+
|
|
33
|
+
payload = {"db_dir": str(db_path), "execute_cleanup": execute_cleanup}
|
|
34
|
+
|
|
35
|
+
chapter.run(payload, {})
|
|
36
|
+
print("\n[CLEANUP] Data execution explicitly removed cleanly.")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
if len(sys.argv) < 2:
|
|
41
|
+
print("[CLEANUP] Critical Error: Expected target directory as first argument.")
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
|
|
44
|
+
execute(sys.argv[1])
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Logical implementation hooks extracted from standard Bootstrap CLM Manifests.
|
|
3
|
+
Allows the YAML manifests to be devoid of massive inline implementation logic.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def execute_cleanup(context: dict) -> dict:
|
|
8
|
+
"""
|
|
9
|
+
Executes the cleanup logic explicitly wiping redundant duplicate content.
|
|
10
|
+
Extracted from cleanup_procedure.yaml
|
|
11
|
+
"""
|
|
12
|
+
identities_db = context.get("identities_db")
|
|
13
|
+
content_db = context.get("content_db")
|
|
14
|
+
log_db = context.get("log_db")
|
|
15
|
+
|
|
16
|
+
if not identities_db or not content_db:
|
|
17
|
+
return {"status": "error", "message": "Missing topological database"}
|
|
18
|
+
|
|
19
|
+
print("\\n[CLEANUP] Requested deduplication on database.")
|
|
20
|
+
|
|
21
|
+
# A simple deduplication pass: if we have multiple hashes mapping to the identical content bytes,
|
|
22
|
+
# we leave the earliest (oldest) one and prune the rest to strictly save space and maintain topological soundness.
|
|
23
|
+
content_hashes_seen = set()
|
|
24
|
+
duplicates_removed = 0
|
|
25
|
+
|
|
26
|
+
all_cards = content_db.get_all_mcards_raw()
|
|
27
|
+
|
|
28
|
+
for card in all_cards:
|
|
29
|
+
# Maintain purely unique content. If content already exists, it is functionally redundant.
|
|
30
|
+
if card.content in content_hashes_seen:
|
|
31
|
+
content_db.delete(card.hash)
|
|
32
|
+
duplicates_removed += 1
|
|
33
|
+
else:
|
|
34
|
+
content_hashes_seen.add(card.content)
|
|
35
|
+
|
|
36
|
+
print(
|
|
37
|
+
f"[CLEANUP] Successfully wiped and decoupled isolated duplicates from disk. Deduped {duplicates_removed} cards."
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Record the cleanup execution natively into logs
|
|
41
|
+
if log_db:
|
|
42
|
+
from clm.layer0.model.card import MCard
|
|
43
|
+
|
|
44
|
+
log_message = (
|
|
45
|
+
f"Execution Trace: Deduplicated {duplicates_removed} cards dynamically."
|
|
46
|
+
)
|
|
47
|
+
log_db.add(MCard(log_message))
|
|
48
|
+
|
|
49
|
+
return {"status": "success", "duplicates_removed": duplicates_removed}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from clm.layer2.card_collection import CardCollection
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def execute(target_dir: str):
|
|
8
|
+
"""
|
|
9
|
+
Executes the Genesis Bootstrapping Procedure natively against the sandbox.
|
|
10
|
+
"""
|
|
11
|
+
import importlib.util
|
|
12
|
+
|
|
13
|
+
if importlib.util.find_spec("clm.layer0.loader") is None:
|
|
14
|
+
print(
|
|
15
|
+
"[BOOTSTRAP] Critical Error: clm core modules not detected. Ensure uv dependencies are synchronized."
|
|
16
|
+
)
|
|
17
|
+
sys.exit(1)
|
|
18
|
+
|
|
19
|
+
from clm.cross_cutting.config.settings import settings
|
|
20
|
+
|
|
21
|
+
bs_dir = Path(target_dir)
|
|
22
|
+
db_path = bs_dir / settings.bootstrap.db_dir
|
|
23
|
+
db_path.mkdir(parents=True, exist_ok=True)
|
|
24
|
+
|
|
25
|
+
idx_db = CardCollection(db_path=str(db_path / settings.bootstrap.identity_db_name))
|
|
26
|
+
cont_db = CardCollection(db_path=str(db_path / settings.bootstrap.content_db_name))
|
|
27
|
+
log_db = CardCollection(db_path=str(db_path / settings.bootstrap.log_db_name))
|
|
28
|
+
|
|
29
|
+
yaml_path = (
|
|
30
|
+
bs_dir / settings.bootstrap.manifests_dir / settings.bootstrap.genesis_manifest
|
|
31
|
+
)
|
|
32
|
+
if not yaml_path.exists():
|
|
33
|
+
print(f"[BOOTSTRAP] Critical Error: Genesis schematic missing at {yaml_path}")
|
|
34
|
+
sys.exit(1)
|
|
35
|
+
|
|
36
|
+
from clm.layer1.engine import PTREngine
|
|
37
|
+
|
|
38
|
+
engine = PTREngine(storage_collection=cont_db)
|
|
39
|
+
|
|
40
|
+
payload = {
|
|
41
|
+
"identities_db": idx_db,
|
|
42
|
+
"content_db": cont_db,
|
|
43
|
+
"log_db": log_db,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
from clm.layer0.model.card import MCard
|
|
47
|
+
|
|
48
|
+
dummy_target = MCard("genesis_bootstrap_target")
|
|
49
|
+
cont_db.add(dummy_target)
|
|
50
|
+
target_hash = dummy_target.hash
|
|
51
|
+
|
|
52
|
+
pcard_ref = f"file://{yaml_path.absolute()}"
|
|
53
|
+
print(f"\n[BOOTSTRAP] Initiating Petri Net Flow: {yaml_path.name}")
|
|
54
|
+
|
|
55
|
+
result = engine.execute_net(pcard_ref, target_hash, context=payload) # type: ignore
|
|
56
|
+
|
|
57
|
+
if result.deadlocked or not result.completed:
|
|
58
|
+
print("\n[BOOTSTRAP] Genesis execution failed or deadlocked.")
|
|
59
|
+
if result.firings:
|
|
60
|
+
for f in result.firings:
|
|
61
|
+
if not f.success:
|
|
62
|
+
print(f" - Transition {f.transition_name} failed: {f.error}")
|
|
63
|
+
sys.exit(1)
|
|
64
|
+
|
|
65
|
+
print(
|
|
66
|
+
"\n[BOOTSTRAP] Genesis execution successfully verified and initialized fully natively."
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
if len(sys.argv) < 2:
|
|
72
|
+
print(
|
|
73
|
+
"[BOOTSTRAP] Critical Error: Expected target directory as first argument."
|
|
74
|
+
)
|
|
75
|
+
sys.exit(1)
|
|
76
|
+
|
|
77
|
+
execute(sys.argv[1])
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Phase B: Schema Injection Module.
|
|
2
|
+
|
|
3
|
+
Handles mapping abstract external configurations (YAML, text, binary blobs) into
|
|
4
|
+
concrete MCard Database structures. Derives Categorical Typologies and securely
|
|
5
|
+
populates information into the tri-database mesh using the Universal Polyglot structure.
|
|
6
|
+
|
|
7
|
+
Incorporates the 5-E Framework by aggressively profiling informational density
|
|
8
|
+
(Entropy) at the categorical inference stage.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
import mimetypes
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import scipy.stats
|
|
18
|
+
import yaml
|
|
19
|
+
|
|
20
|
+
from clm.layer0.model.card import MCard
|
|
21
|
+
from clm.layer2.card_collection import CardCollection
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def compute_shannon_entropy(data: bytes) -> float:
|
|
27
|
+
"""Compute the Shannon Entropy of the byte sequence for the 5-E framework.
|
|
28
|
+
|
|
29
|
+
This acts as a heuristic for Information Density and topological chaos limits.
|
|
30
|
+
"""
|
|
31
|
+
if not data:
|
|
32
|
+
return 0.0
|
|
33
|
+
_, counts = np.unique(list(data), return_counts=True)
|
|
34
|
+
return float(scipy.stats.entropy(counts, base=2))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SchemaInjector:
|
|
38
|
+
"""Injects and normalizes external configurations/blobs into the 3-table MCard Data Plane."""
|
|
39
|
+
|
|
40
|
+
def __init__(self, target_collection: CardCollection) -> None:
|
|
41
|
+
"""Initialize the injector against a sovereign boundary.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
target_collection: The root or isolated collection acting as the target Database.
|
|
45
|
+
"""
|
|
46
|
+
self.collection = target_collection
|
|
47
|
+
|
|
48
|
+
def inject_blob(
|
|
49
|
+
self,
|
|
50
|
+
content: bytes,
|
|
51
|
+
handle_name: str | None = None,
|
|
52
|
+
inferred_mime: str | None = None,
|
|
53
|
+
) -> tuple[MCard, float]:
|
|
54
|
+
"""Inject an abstract binary/text blob into the structured Data Plane.
|
|
55
|
+
|
|
56
|
+
Evaluates the 5-E Entropy framework against the content, instantiates the MCard,
|
|
57
|
+
and derives a generic Categorical Topology wrapper.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
content: The raw byte content.
|
|
61
|
+
handle_name: Optional persistent PKI/handle routing registry.
|
|
62
|
+
inferred_mime: Optional categorical modality.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Tuple of the materialized MCard and its computed Shannon Entropy.
|
|
66
|
+
"""
|
|
67
|
+
entropy = compute_shannon_entropy(content)
|
|
68
|
+
mcard = MCard(content)
|
|
69
|
+
|
|
70
|
+
if handle_name:
|
|
71
|
+
if not self.collection.resolve_handle(handle_name):
|
|
72
|
+
self.collection.add_with_handle(mcard, handle_name)
|
|
73
|
+
logger.info(
|
|
74
|
+
f"Injected new MCard -> Handle '{handle_name}' (Entropy: {entropy:.4f})"
|
|
75
|
+
)
|
|
76
|
+
else:
|
|
77
|
+
self.collection.engine.update_handle(handle_name, mcard.hash)
|
|
78
|
+
logger.info(
|
|
79
|
+
f"Updated Handle '{handle_name}' -> New Hash: {mcard.hash[:8]} (Entropy: {entropy:.4f})"
|
|
80
|
+
)
|
|
81
|
+
else:
|
|
82
|
+
self.collection.add(mcard)
|
|
83
|
+
|
|
84
|
+
# Log categorical typologies
|
|
85
|
+
logger.debug(
|
|
86
|
+
f"Categorical Inference: MIME={inferred_mime or 'application/octet-stream'}, Entropy={entropy:.4f}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return mcard, entropy
|
|
90
|
+
|
|
91
|
+
def inject_file(
|
|
92
|
+
self, file_path: Path, explicit_handle: str | None = None
|
|
93
|
+
) -> tuple[MCard, float]:
|
|
94
|
+
"""Load an external file and dynamically infer its topological placement.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
file_path: Physical disk path to inject.
|
|
98
|
+
explicit_handle: Optional handle. If none, falls back to `file://{name}`.
|
|
99
|
+
"""
|
|
100
|
+
if not file_path.exists() or not file_path.is_file():
|
|
101
|
+
raise FileNotFoundError(
|
|
102
|
+
f"Cannot inject missing or non-file path: {file_path}"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
mime_type, _ = mimetypes.guess_type(str(file_path))
|
|
106
|
+
mime_type = mime_type or "application/octet-stream"
|
|
107
|
+
|
|
108
|
+
handle = explicit_handle or f"file://{file_path.name}"
|
|
109
|
+
raw_bytes = file_path.read_bytes()
|
|
110
|
+
|
|
111
|
+
return self.inject_blob(raw_bytes, handle_name=handle, inferred_mime=mime_type)
|
|
112
|
+
|
|
113
|
+
def inject_yaml_schema(
|
|
114
|
+
self, clm_dict: dict[str, Any], handle_name: str | None = None
|
|
115
|
+
) -> tuple[MCard, float]:
|
|
116
|
+
"""Inject a rigorously structured dictionary acting as a Categorical Schema or CLM PCard.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
clm_dict: Abstract Specification dictionary.
|
|
120
|
+
handle_name: Address.
|
|
121
|
+
"""
|
|
122
|
+
content_bytes = yaml.dump(clm_dict, sort_keys=False).encode("utf-8")
|
|
123
|
+
return self.inject_blob(
|
|
124
|
+
content_bytes, handle_name=handle_name, inferred_mime="application/x-yaml"
|
|
125
|
+
)
|