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,334 @@
|
|
|
1
|
+
"""Tabular Baldwin Modularity Manipulator (Sprint 393 / DEL-393-02).
|
|
2
|
+
|
|
3
|
+
Algebraic operations over CSV and tabular datasets:
|
|
4
|
+
- split: Partition dataset by ratio (e.g., train/test) or predicate filter.
|
|
5
|
+
- substitute: Map/replace values in columns or rename columns.
|
|
6
|
+
- augment: Add derived columns computed from existing fields.
|
|
7
|
+
- exclude: Redact sensitive columns (PII removal) or filter out rows.
|
|
8
|
+
- invert: Invert row order or transpose tabular matrix.
|
|
9
|
+
- port: Transcode CSV to JSON objects or structured records.
|
|
10
|
+
|
|
11
|
+
Layer 1 module (no imports above L1).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import csv
|
|
17
|
+
import io
|
|
18
|
+
import json
|
|
19
|
+
import random
|
|
20
|
+
import re
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TabularManipulator:
|
|
25
|
+
"""Modality manipulator for tabular CSV/structured table data."""
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def _parse_csv(data: str | bytes) -> tuple[list[str], list[list[str]]]:
|
|
29
|
+
"""Parse raw CSV string or bytes into headers and rows."""
|
|
30
|
+
text = data.decode("utf-8") if isinstance(data, bytes) else str(data)
|
|
31
|
+
reader = csv.reader(io.StringIO(text))
|
|
32
|
+
rows = [r for r in reader if r]
|
|
33
|
+
if not rows:
|
|
34
|
+
return [], []
|
|
35
|
+
headers = rows[0]
|
|
36
|
+
data_rows = rows[1:]
|
|
37
|
+
return headers, data_rows
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def _render_csv(headers: list[str], rows: list[list[str]]) -> str:
|
|
41
|
+
"""Render headers and rows back into standard CSV string."""
|
|
42
|
+
out = io.StringIO()
|
|
43
|
+
writer = csv.writer(out, lineterminator="\n")
|
|
44
|
+
if headers:
|
|
45
|
+
writer.writerow(headers)
|
|
46
|
+
writer.writerows(rows)
|
|
47
|
+
return out.getvalue()
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def split(
|
|
51
|
+
cls,
|
|
52
|
+
data: str | bytes,
|
|
53
|
+
parameters: dict[str, Any] | None = None,
|
|
54
|
+
) -> dict[str, str]:
|
|
55
|
+
"""Split a tabular dataset into orthogonal partitions.
|
|
56
|
+
|
|
57
|
+
Parameters:
|
|
58
|
+
ratios: dict of partition name -> float ratio (e.g. {'train': 0.8, 'test': 0.2})
|
|
59
|
+
seed: optional random seed for deterministic shuffling
|
|
60
|
+
predicate: optional predicate formula (e.g. "status == 'active'")
|
|
61
|
+
"""
|
|
62
|
+
params = parameters or {}
|
|
63
|
+
headers, rows = cls._parse_csv(data)
|
|
64
|
+
if not rows:
|
|
65
|
+
return {"part_1": cls._render_csv(headers, []), "part_2": cls._render_csv(headers, [])}
|
|
66
|
+
|
|
67
|
+
ratios = params.get("ratios")
|
|
68
|
+
predicate = params.get("predicate") or params.get("condition")
|
|
69
|
+
|
|
70
|
+
if predicate and headers:
|
|
71
|
+
# Split into match vs non-match
|
|
72
|
+
# Simple expression evaluation over row dict
|
|
73
|
+
matched: list[list[str]] = []
|
|
74
|
+
unmatched: list[list[str]] = []
|
|
75
|
+
for r in rows:
|
|
76
|
+
row_dict = dict(zip(headers, r))
|
|
77
|
+
val = cls._eval_simple_condition(predicate, row_dict)
|
|
78
|
+
if val:
|
|
79
|
+
matched.append(r)
|
|
80
|
+
else:
|
|
81
|
+
unmatched.append(r)
|
|
82
|
+
return {
|
|
83
|
+
"matched": cls._render_csv(headers, matched),
|
|
84
|
+
"unmatched": cls._render_csv(headers, unmatched),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if ratios:
|
|
88
|
+
seed = params.get("seed")
|
|
89
|
+
shuffled_rows = list(rows)
|
|
90
|
+
if seed is not None:
|
|
91
|
+
rng = random.Random(seed)
|
|
92
|
+
rng.shuffle(shuffled_rows)
|
|
93
|
+
|
|
94
|
+
total = len(shuffled_rows)
|
|
95
|
+
partitions: dict[str, str] = {}
|
|
96
|
+
current_idx = 0
|
|
97
|
+
items = list(ratios.items())
|
|
98
|
+
|
|
99
|
+
for i, (name, ratio) in enumerate(items):
|
|
100
|
+
if i == len(items) - 1:
|
|
101
|
+
# Last partition gets all remainder to guarantee exact Noetherian conservation
|
|
102
|
+
part_rows = shuffled_rows[current_idx:]
|
|
103
|
+
else:
|
|
104
|
+
count = int(round(total * ratio))
|
|
105
|
+
part_rows = shuffled_rows[current_idx : current_idx + count]
|
|
106
|
+
current_idx += count
|
|
107
|
+
partitions[name] = cls._render_csv(headers, part_rows)
|
|
108
|
+
return partitions
|
|
109
|
+
|
|
110
|
+
# Default 50/50 split
|
|
111
|
+
mid = len(rows) // 2
|
|
112
|
+
return {
|
|
113
|
+
"part_1": cls._render_csv(headers, rows[:mid]),
|
|
114
|
+
"part_2": cls._render_csv(headers, rows[mid:]),
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def substitute(
|
|
119
|
+
cls,
|
|
120
|
+
data: str | bytes,
|
|
121
|
+
parameters: dict[str, Any] | None = None,
|
|
122
|
+
) -> str:
|
|
123
|
+
"""Substitute column names or column values in tabular data.
|
|
124
|
+
|
|
125
|
+
Parameters:
|
|
126
|
+
rename_columns: dict of old_name -> new_name
|
|
127
|
+
value_map: dict of column_name -> dict of old_val -> new_val
|
|
128
|
+
"""
|
|
129
|
+
params = parameters or {}
|
|
130
|
+
headers, rows = cls._parse_csv(data)
|
|
131
|
+
rename = params.get("rename_columns", {})
|
|
132
|
+
value_map = params.get("value_map", {})
|
|
133
|
+
|
|
134
|
+
new_headers = [rename.get(h, h) for h in headers]
|
|
135
|
+
col_to_idx = {h: idx for idx, h in enumerate(headers)}
|
|
136
|
+
|
|
137
|
+
new_rows: list[list[str]] = []
|
|
138
|
+
for r in rows:
|
|
139
|
+
new_r = list(r)
|
|
140
|
+
for col, mapping in value_map.items():
|
|
141
|
+
if col in col_to_idx and col_to_idx[col] < len(new_r):
|
|
142
|
+
val = new_r[col_to_idx[col]]
|
|
143
|
+
if val in mapping:
|
|
144
|
+
new_r[col_to_idx[col]] = str(mapping[val])
|
|
145
|
+
new_rows.append(new_r)
|
|
146
|
+
|
|
147
|
+
return cls._render_csv(new_headers, new_rows)
|
|
148
|
+
|
|
149
|
+
@classmethod
|
|
150
|
+
def augment(
|
|
151
|
+
cls,
|
|
152
|
+
data: str | bytes,
|
|
153
|
+
parameters: dict[str, Any] | None = None,
|
|
154
|
+
) -> str:
|
|
155
|
+
"""Augment tabular data with a new derived column.
|
|
156
|
+
|
|
157
|
+
Parameters:
|
|
158
|
+
target_column: name of new column
|
|
159
|
+
source_column: optional source column
|
|
160
|
+
formula: expression or mapping logic
|
|
161
|
+
constant_value: optional constant value
|
|
162
|
+
"""
|
|
163
|
+
params = parameters or {}
|
|
164
|
+
headers, rows = cls._parse_csv(data)
|
|
165
|
+
target_col = params.get("column_name") or params.get("target_column") or "augmented_col"
|
|
166
|
+
source_col = params.get("source_column")
|
|
167
|
+
formula = params.get("formula")
|
|
168
|
+
constant_val = params.get("default_value") if params.get("default_value") is not None else params.get("constant_value")
|
|
169
|
+
|
|
170
|
+
new_headers = list(headers) + [target_col]
|
|
171
|
+
col_to_idx = {h: idx for idx, h in enumerate(headers)}
|
|
172
|
+
new_rows: list[list[str]] = []
|
|
173
|
+
|
|
174
|
+
for r in rows:
|
|
175
|
+
row_dict = dict(zip(headers, r))
|
|
176
|
+
if constant_val is not None:
|
|
177
|
+
val = str(constant_val)
|
|
178
|
+
elif formula:
|
|
179
|
+
val = cls._eval_formula(formula, row_dict)
|
|
180
|
+
elif source_col and source_col in col_to_idx:
|
|
181
|
+
val = r[col_to_idx[source_col]]
|
|
182
|
+
else:
|
|
183
|
+
val = ""
|
|
184
|
+
new_rows.append(list(r) + [val])
|
|
185
|
+
|
|
186
|
+
return cls._render_csv(new_headers, new_rows)
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def exclude(
|
|
190
|
+
cls,
|
|
191
|
+
data: str | bytes,
|
|
192
|
+
parameters: dict[str, Any] | None = None,
|
|
193
|
+
) -> str:
|
|
194
|
+
"""Exclude (drop) columns or filter out rows.
|
|
195
|
+
|
|
196
|
+
Parameters:
|
|
197
|
+
columns: list of column names to redact/drop
|
|
198
|
+
condition: optional row condition to exclude
|
|
199
|
+
"""
|
|
200
|
+
params = parameters or {}
|
|
201
|
+
headers, rows = cls._parse_csv(data)
|
|
202
|
+
drop_cols = set(params.get("columns") or params.get("target_columns") or [])
|
|
203
|
+
condition = params.get("condition") or params.get("predicate")
|
|
204
|
+
|
|
205
|
+
# Column projection
|
|
206
|
+
keep_indices = [i for i, h in enumerate(headers) if h not in drop_cols]
|
|
207
|
+
new_headers = [headers[i] for i in keep_indices]
|
|
208
|
+
|
|
209
|
+
new_rows: list[list[str]] = []
|
|
210
|
+
for r in rows:
|
|
211
|
+
row_dict = dict(zip(headers, r))
|
|
212
|
+
if condition and cls._eval_simple_condition(condition, row_dict):
|
|
213
|
+
# Exclude matching rows
|
|
214
|
+
continue
|
|
215
|
+
new_rows.append([r[i] for i in keep_indices if i < len(r)])
|
|
216
|
+
|
|
217
|
+
return cls._render_csv(new_headers, new_rows)
|
|
218
|
+
|
|
219
|
+
@classmethod
|
|
220
|
+
def invert(
|
|
221
|
+
cls,
|
|
222
|
+
data: str | bytes,
|
|
223
|
+
parameters: dict[str, Any] | None = None,
|
|
224
|
+
) -> str:
|
|
225
|
+
"""Invert tabular data by reversing rows or transposing.
|
|
226
|
+
|
|
227
|
+
Parameters:
|
|
228
|
+
strategy: 'reverse_rows' (default) or 'transpose'
|
|
229
|
+
"""
|
|
230
|
+
params = parameters or {}
|
|
231
|
+
strategy = params.get("strategy", "reverse_rows")
|
|
232
|
+
headers, rows = cls._parse_csv(data)
|
|
233
|
+
|
|
234
|
+
if strategy == "transpose" and headers:
|
|
235
|
+
all_matrix = [headers] + rows
|
|
236
|
+
transposed = list(map(list, zip(*all_matrix)))
|
|
237
|
+
new_headers = transposed[0] if transposed else []
|
|
238
|
+
new_rows = transposed[1:] if len(transposed) > 1 else []
|
|
239
|
+
return cls._render_csv(new_headers, new_rows)
|
|
240
|
+
|
|
241
|
+
# Default: reverse row order
|
|
242
|
+
reversed_rows = list(reversed(rows))
|
|
243
|
+
return cls._render_csv(headers, reversed_rows)
|
|
244
|
+
|
|
245
|
+
@classmethod
|
|
246
|
+
def port(
|
|
247
|
+
cls,
|
|
248
|
+
data: str | bytes,
|
|
249
|
+
parameters: dict[str, Any] | None = None,
|
|
250
|
+
) -> str:
|
|
251
|
+
"""Port tabular data across representations (e.g. CSV to JSON array).
|
|
252
|
+
|
|
253
|
+
Parameters:
|
|
254
|
+
target_format: 'json' (default) or 'tsv'
|
|
255
|
+
"""
|
|
256
|
+
params = parameters or {}
|
|
257
|
+
target_fmt = params.get("target_format", "json").lower()
|
|
258
|
+
headers, rows = cls._parse_csv(data)
|
|
259
|
+
|
|
260
|
+
if target_fmt == "json":
|
|
261
|
+
records = [dict(zip(headers, r)) for r in rows]
|
|
262
|
+
return json.dumps(records, indent=2)
|
|
263
|
+
elif target_fmt == "tsv":
|
|
264
|
+
out = io.StringIO()
|
|
265
|
+
writer = csv.writer(out, delimiter="\t", lineterminator="\n")
|
|
266
|
+
if headers:
|
|
267
|
+
writer.writerow(headers)
|
|
268
|
+
writer.writerows(rows)
|
|
269
|
+
return out.getvalue()
|
|
270
|
+
return cls._render_csv(headers, rows)
|
|
271
|
+
|
|
272
|
+
@staticmethod
|
|
273
|
+
def _eval_simple_condition(condition: str, row: dict[str, str]) -> bool:
|
|
274
|
+
"""Safely evaluate simple conditions like 'col == val' or 'col != val' without eval()."""
|
|
275
|
+
cond = condition.strip()
|
|
276
|
+
# Check !=
|
|
277
|
+
if "!=" in cond:
|
|
278
|
+
parts = cond.split("!=", 1)
|
|
279
|
+
col = parts[0].strip().strip("'\"")
|
|
280
|
+
target = parts[1].strip().strip("'\"")
|
|
281
|
+
return str(row.get(col, "")) != target
|
|
282
|
+
# Check ==
|
|
283
|
+
if "==" in cond:
|
|
284
|
+
parts = cond.split("==", 1)
|
|
285
|
+
col = parts[0].strip().strip("'\"")
|
|
286
|
+
target = parts[1].strip().strip("'\"")
|
|
287
|
+
return str(row.get(col, "")) == target
|
|
288
|
+
# Check >=
|
|
289
|
+
if ">=" in cond:
|
|
290
|
+
parts = cond.split(">=", 1)
|
|
291
|
+
col = parts[0].strip()
|
|
292
|
+
target = float(parts[1].strip())
|
|
293
|
+
return float(row.get(col, 0)) >= target
|
|
294
|
+
# Check <=
|
|
295
|
+
if "<=" in cond:
|
|
296
|
+
parts = cond.split("<=", 1)
|
|
297
|
+
col = parts[0].strip()
|
|
298
|
+
target = float(parts[1].strip())
|
|
299
|
+
return float(row.get(col, 0)) <= target
|
|
300
|
+
# Check >
|
|
301
|
+
if ">" in cond:
|
|
302
|
+
parts = cond.split(">", 1)
|
|
303
|
+
col = parts[0].strip()
|
|
304
|
+
target = float(parts[1].strip())
|
|
305
|
+
return float(row.get(col, 0)) > target
|
|
306
|
+
# Check <
|
|
307
|
+
if "<" in cond:
|
|
308
|
+
parts = cond.split("<", 1)
|
|
309
|
+
col = parts[0].strip()
|
|
310
|
+
target = float(parts[1].strip())
|
|
311
|
+
return float(row.get(col, 0)) < target
|
|
312
|
+
|
|
313
|
+
return bool(row.get(cond))
|
|
314
|
+
|
|
315
|
+
@staticmethod
|
|
316
|
+
def _eval_formula(formula: str, row: dict[str, str]) -> str:
|
|
317
|
+
"""Safely evaluate formula/tier rules (e.g. ternary or string replacement)."""
|
|
318
|
+
f = formula.strip()
|
|
319
|
+
# Ternary pattern: cond ? 'val1' : 'val2'
|
|
320
|
+
ternary_match = re.match(r"(.+?)\s*\?\s*['\"](.*?)['\"]\s*:\s*['\"](.*?)['\"]", f)
|
|
321
|
+
if ternary_match:
|
|
322
|
+
cond, true_val, false_val = ternary_match.groups()
|
|
323
|
+
if TabularManipulator._eval_simple_condition(cond, row):
|
|
324
|
+
return true_val
|
|
325
|
+
return false_val
|
|
326
|
+
|
|
327
|
+
# Interpolation pattern: {col1}_{col2}
|
|
328
|
+
if "{" in f and "}" in f:
|
|
329
|
+
res = f
|
|
330
|
+
for k, v in row.items():
|
|
331
|
+
res = res.replace(f"{{{k}}}", str(v))
|
|
332
|
+
return res
|
|
333
|
+
|
|
334
|
+
return f
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Baldwin Port Operator (DEL-388-02).
|
|
2
|
+
|
|
3
|
+
Translation Operator (->): A_X -> A_Y.
|
|
4
|
+
Migrates an implementation across heterogeneous host runtime domains
|
|
5
|
+
(e.g., Python -> Rust / Wasm / Bash) without altering its logical abstract
|
|
6
|
+
specification or balanced invariants, preserving triadic syntactic closure.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import copy
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
import yaml
|
|
14
|
+
|
|
15
|
+
from clm.layer0.model.card import MCard
|
|
16
|
+
from clm.layer1.operations.split import _parse_manifest, ensure_triadic_closure
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def op_port(impl: dict[str, Any], target: MCard, ctx: dict[str, Any]) -> dict[str, Any]:
|
|
20
|
+
"""Execute the Baldwin Port (->) operation.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
impl: Configuration dict for port:
|
|
24
|
+
target_runtime (str): Target runtime (e.g. "rust", "wasm", "node", "bash").
|
|
25
|
+
target: Target MCard to port.
|
|
26
|
+
ctx: Execution context.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Dict containing the ported manifest, new MCard, and closure proof.
|
|
30
|
+
"""
|
|
31
|
+
manifest = _parse_manifest(target)
|
|
32
|
+
target_runtime = impl.get("target_runtime", ctx.get("target_runtime", "rust"))
|
|
33
|
+
|
|
34
|
+
updated = copy.deepcopy(manifest)
|
|
35
|
+
|
|
36
|
+
# Concrete implementation is adapted to target runtime
|
|
37
|
+
c_impl = updated.get("concrete_impl", {})
|
|
38
|
+
if isinstance(c_impl, dict):
|
|
39
|
+
orig_runtime = c_impl.get("runtime", "python")
|
|
40
|
+
c_impl["runtime"] = target_runtime
|
|
41
|
+
c_impl["ported_from"] = orig_runtime
|
|
42
|
+
else:
|
|
43
|
+
updated["concrete_impl"] = {
|
|
44
|
+
"runtime": target_runtime,
|
|
45
|
+
"ported_from": "python",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Abstract spec and balanced expectations remain invariant
|
|
49
|
+
final_manifest = ensure_triadic_closure(updated)
|
|
50
|
+
yaml_content = yaml.dump(final_manifest, default_flow_style=False)
|
|
51
|
+
new_card = MCard(yaml_content)
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
"success": True,
|
|
55
|
+
"operator": "port",
|
|
56
|
+
"target_runtime": target_runtime,
|
|
57
|
+
"syntactic_closure": True,
|
|
58
|
+
"manifest": final_manifest,
|
|
59
|
+
"hash": new_card.hash,
|
|
60
|
+
"content": yaml_content,
|
|
61
|
+
"mcard": new_card,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
__all__ = ["op_port"]
|