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,553 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Collection Manager - Dynamic CLM assembly using MCard Collections
|
|
3
|
+
|
|
4
|
+
Manages the dynamic assembly of CLM specifications from individual
|
|
5
|
+
components stored in MCard Collections, providing a high-level interface
|
|
6
|
+
for PTR operations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from datetime import datetime, timezone
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from clm.layer0.algebra import AssembledCLM, CLMAssembler
|
|
15
|
+
from clm.layer0.loader import YAMLTemplateLoader
|
|
16
|
+
from clm.layer2.card_collection import CardCollection
|
|
17
|
+
|
|
18
|
+
from .storage import MCardStorage
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class CollectionStats:
|
|
23
|
+
"""Statistics for a managed collection"""
|
|
24
|
+
|
|
25
|
+
total_cards: int
|
|
26
|
+
pcard_count: int
|
|
27
|
+
vcard_count: int
|
|
28
|
+
clm_component_count: int
|
|
29
|
+
assembled_clm_count: int
|
|
30
|
+
last_updated: datetime
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class CollectionManager:
|
|
34
|
+
"""
|
|
35
|
+
High-level manager for PTR operations using MCard Collections.
|
|
36
|
+
|
|
37
|
+
This class provides:
|
|
38
|
+
- Dynamic CLM assembly from components
|
|
39
|
+
- PCard and VCard management
|
|
40
|
+
- Template loading and storage
|
|
41
|
+
- Search and discovery capabilities
|
|
42
|
+
- Statistics and monitoring
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, collection: CardCollection = None):
|
|
46
|
+
self.logger = logging.getLogger(__name__)
|
|
47
|
+
self.collection = collection or CardCollection()
|
|
48
|
+
|
|
49
|
+
# Initialize sub-components
|
|
50
|
+
self.storage = MCardStorage(self.collection)
|
|
51
|
+
self.template_loader = YAMLTemplateLoader(storage_collection=self.collection)
|
|
52
|
+
self.clm_assembler = CLMAssembler(
|
|
53
|
+
storage_collection=self.collection, template_loader=self.template_loader
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
self.logger.info("Collection Manager initialized")
|
|
57
|
+
|
|
58
|
+
def create_pcard_from_templates(
|
|
59
|
+
self,
|
|
60
|
+
abstract_template: str,
|
|
61
|
+
concrete_template: str,
|
|
62
|
+
balanced_template: str,
|
|
63
|
+
name: str = None,
|
|
64
|
+
metadata: dict[str, Any] = None,
|
|
65
|
+
) -> dict[str, Any]:
|
|
66
|
+
"""
|
|
67
|
+
Create a complete PCard from YAML templates.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
abstract_template: YAML content for abstract dimension
|
|
71
|
+
concrete_template: YAML content for concrete dimension
|
|
72
|
+
balanced_template: YAML content for balanced dimension
|
|
73
|
+
name: Optional name for the PCard
|
|
74
|
+
metadata: Additional metadata
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dictionary with creation results and hashes
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
# Parse templates
|
|
81
|
+
import yaml
|
|
82
|
+
|
|
83
|
+
abstract_data = yaml.safe_load(abstract_template)
|
|
84
|
+
concrete_data = yaml.safe_load(concrete_template)
|
|
85
|
+
balanced_data = yaml.safe_load(balanced_template)
|
|
86
|
+
|
|
87
|
+
# Create PCard content
|
|
88
|
+
pcard_content = {
|
|
89
|
+
"abstract": abstract_data,
|
|
90
|
+
"concrete": concrete_data,
|
|
91
|
+
"balanced": balanced_data,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Add metadata
|
|
95
|
+
pcard_metadata = {
|
|
96
|
+
"name": name
|
|
97
|
+
or f"PCard_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}",
|
|
98
|
+
"created_from": "templates",
|
|
99
|
+
"template_count": 3,
|
|
100
|
+
}
|
|
101
|
+
if metadata:
|
|
102
|
+
pcard_metadata.update(metadata)
|
|
103
|
+
|
|
104
|
+
# Store PCard
|
|
105
|
+
storage_result = self.storage.store_pcard(pcard_content, pcard_metadata)
|
|
106
|
+
|
|
107
|
+
if not storage_result.success:
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"Failed to store PCard: {storage_result.error_message}"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
self.logger.info(f"Created PCard from templates: {storage_result.hash}")
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
"success": True,
|
|
116
|
+
"pcard_hash": storage_result.hash,
|
|
117
|
+
"metadata": storage_result.metadata,
|
|
118
|
+
"components": {
|
|
119
|
+
"abstract": abstract_data,
|
|
120
|
+
"concrete": concrete_data,
|
|
121
|
+
"balanced": balanced_data,
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
except (yaml.YAMLError, ValueError, TypeError, KeyError) as e:
|
|
126
|
+
self.logger.error(
|
|
127
|
+
f"Failed to create PCard from templates: {str(e)}", exc_info=True
|
|
128
|
+
)
|
|
129
|
+
return {"success": False, "error_message": str(e)}
|
|
130
|
+
|
|
131
|
+
def create_pcard_from_clm_assembly(
|
|
132
|
+
self,
|
|
133
|
+
assembled_clm: AssembledCLM,
|
|
134
|
+
name: str = None,
|
|
135
|
+
metadata: dict[str, Any] = None,
|
|
136
|
+
) -> dict[str, Any]:
|
|
137
|
+
"""
|
|
138
|
+
Create a PCard from an assembled CLM.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
assembled_clm: AssembledCLM object
|
|
142
|
+
name: Optional name for the PCard
|
|
143
|
+
metadata: Additional metadata
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Dictionary with creation results
|
|
147
|
+
"""
|
|
148
|
+
try:
|
|
149
|
+
# Extract CLM content from assembly
|
|
150
|
+
pcard_content = {
|
|
151
|
+
"abstract": assembled_clm.abstract.content,
|
|
152
|
+
"concrete": assembled_clm.concrete.content,
|
|
153
|
+
"balanced": assembled_clm.balanced.content,
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# Create metadata
|
|
157
|
+
pcard_metadata = {
|
|
158
|
+
"name": name or assembled_clm.name,
|
|
159
|
+
"created_from": "clm_assembly",
|
|
160
|
+
"assembly_hash": assembled_clm.assembly_hash,
|
|
161
|
+
"validation": {
|
|
162
|
+
"is_valid": assembled_clm.validation_result.is_valid,
|
|
163
|
+
"errors": assembled_clm.validation_result.errors,
|
|
164
|
+
"warnings": assembled_clm.validation_result.warnings,
|
|
165
|
+
},
|
|
166
|
+
}
|
|
167
|
+
if metadata:
|
|
168
|
+
pcard_metadata.update(metadata)
|
|
169
|
+
|
|
170
|
+
# Store PCard
|
|
171
|
+
storage_result = self.storage.store_pcard(pcard_content, pcard_metadata)
|
|
172
|
+
|
|
173
|
+
if not storage_result.success:
|
|
174
|
+
raise ValueError(
|
|
175
|
+
f"Failed to store PCard: {storage_result.error_message}"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
self.logger.info(f"Created PCard from CLM assembly: {storage_result.hash}")
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
"success": True,
|
|
182
|
+
"pcard_hash": storage_result.hash,
|
|
183
|
+
"metadata": storage_result.metadata,
|
|
184
|
+
"assembly_hash": assembled_clm.assembly_hash,
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
except (ValueError, TypeError, KeyError, AttributeError) as e:
|
|
188
|
+
self.logger.error(
|
|
189
|
+
f"Failed to create PCard from CLM assembly: {str(e)}", exc_info=True
|
|
190
|
+
)
|
|
191
|
+
return {"success": False, "error_message": str(e)}
|
|
192
|
+
|
|
193
|
+
def assemble_clm_from_components(
|
|
194
|
+
self,
|
|
195
|
+
abstract_name: str,
|
|
196
|
+
concrete_name: str,
|
|
197
|
+
balanced_name: str,
|
|
198
|
+
assembly_name: str = None,
|
|
199
|
+
) -> dict[str, Any]:
|
|
200
|
+
"""
|
|
201
|
+
Assemble a complete CLM from individual component templates.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
abstract_name: Name of abstract template
|
|
205
|
+
concrete_name: Name of concrete template
|
|
206
|
+
balanced_name: Name of balanced template
|
|
207
|
+
assembly_name: Optional name for the assembled CLM
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Dictionary with assembly results
|
|
211
|
+
"""
|
|
212
|
+
try:
|
|
213
|
+
# Load templates
|
|
214
|
+
abstract_template = self.template_loader.get_template(
|
|
215
|
+
"abstract", abstract_name
|
|
216
|
+
)
|
|
217
|
+
concrete_template = self.template_loader.get_template(
|
|
218
|
+
"concrete", concrete_name
|
|
219
|
+
)
|
|
220
|
+
balanced_template = self.template_loader.get_template(
|
|
221
|
+
"balanced", balanced_name
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
if not abstract_template:
|
|
225
|
+
raise ValueError(f"Abstract template not found: {abstract_name}")
|
|
226
|
+
if not concrete_template:
|
|
227
|
+
raise ValueError(f"Concrete template not found: {concrete_name}")
|
|
228
|
+
if not balanced_template:
|
|
229
|
+
raise ValueError(f"Balanced template not found: {balanced_name}")
|
|
230
|
+
|
|
231
|
+
# Create components from templates
|
|
232
|
+
abstract_component = self.clm_assembler.create_component_from_template(
|
|
233
|
+
"abstract", abstract_name, abstract_template.content
|
|
234
|
+
)
|
|
235
|
+
concrete_component = self.clm_assembler.create_component_from_template(
|
|
236
|
+
"concrete", concrete_name, concrete_template.content
|
|
237
|
+
)
|
|
238
|
+
balanced_component = self.clm_assembler.create_component_from_template(
|
|
239
|
+
"balanced", balanced_name, balanced_template.content
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
# Assemble CLM
|
|
243
|
+
assembled_clm = self.clm_assembler.assemble_clm(
|
|
244
|
+
abstract_component.mcard_hash,
|
|
245
|
+
concrete_component.mcard_hash,
|
|
246
|
+
balanced_component.mcard_hash,
|
|
247
|
+
assembly_name,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
self.logger.info(
|
|
251
|
+
f"Assembled CLM: {assembled_clm.name} (valid: {assembled_clm.validation_result.is_valid})"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
"success": True,
|
|
256
|
+
"assembly_hash": assembled_clm.assembly_hash,
|
|
257
|
+
"assembly_name": assembled_clm.name,
|
|
258
|
+
"validation": {
|
|
259
|
+
"is_valid": assembled_clm.validation_result.is_valid,
|
|
260
|
+
"errors": assembled_clm.validation_result.errors,
|
|
261
|
+
"warnings": assembled_clm.validation_result.warnings,
|
|
262
|
+
},
|
|
263
|
+
"components": {
|
|
264
|
+
"abstract": abstract_component.mcard_hash,
|
|
265
|
+
"concrete": concrete_component.mcard_hash,
|
|
266
|
+
"balanced": balanced_component.mcard_hash,
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
except (ValueError, TypeError, KeyError, AttributeError) as e:
|
|
271
|
+
self.logger.error(f"Failed to assemble CLM: {str(e)}", exc_info=True)
|
|
272
|
+
return {"success": False, "error_message": str(e)}
|
|
273
|
+
|
|
274
|
+
def find_executable_pcards(
|
|
275
|
+
self, filters: dict[str, Any] = None
|
|
276
|
+
) -> list[dict[str, Any]]:
|
|
277
|
+
"""
|
|
278
|
+
Find PCards that are ready for execution (valid CLM assembly).
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
filters: Optional filters to apply
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
List of executable PCard information
|
|
285
|
+
"""
|
|
286
|
+
try:
|
|
287
|
+
# Search for PCards
|
|
288
|
+
search_results = self.storage.search_pcards("PCard", filters)
|
|
289
|
+
executable_pcards = []
|
|
290
|
+
|
|
291
|
+
for result in search_results:
|
|
292
|
+
if not result.success:
|
|
293
|
+
continue
|
|
294
|
+
|
|
295
|
+
metadata = result.metadata
|
|
296
|
+
content = result.content
|
|
297
|
+
|
|
298
|
+
# Check if it has all CLM dimensions
|
|
299
|
+
has_all_dimensions = (
|
|
300
|
+
"abstract" in content
|
|
301
|
+
and "concrete" in content
|
|
302
|
+
and "balanced" in content
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# Check validation status
|
|
306
|
+
validation = metadata.get("validation", {})
|
|
307
|
+
is_valid = validation.get(
|
|
308
|
+
"is_valid", True
|
|
309
|
+
) # Assume valid if not specified
|
|
310
|
+
|
|
311
|
+
if has_all_dimensions and is_valid:
|
|
312
|
+
executable_pcards.append(
|
|
313
|
+
{
|
|
314
|
+
"hash": result.metadata.get("hash", "unknown"),
|
|
315
|
+
"name": metadata.get("name", "unnamed"),
|
|
316
|
+
"created_at": metadata.get("created_at"),
|
|
317
|
+
"validation": validation,
|
|
318
|
+
"dimensions": list(content.keys()),
|
|
319
|
+
}
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
self.logger.info(f"Found {len(executable_pcards)} executable PCards")
|
|
323
|
+
|
|
324
|
+
return executable_pcards
|
|
325
|
+
|
|
326
|
+
except (ValueError, TypeError, KeyError, AttributeError) as e:
|
|
327
|
+
self.logger.error(
|
|
328
|
+
f"Failed to find executable PCards: {str(e)}", exc_info=True
|
|
329
|
+
)
|
|
330
|
+
return []
|
|
331
|
+
|
|
332
|
+
def get_clm_components_by_type(
|
|
333
|
+
self, dimension: str, filters: dict[str, Any] = None
|
|
334
|
+
) -> list[dict[str, Any]]:
|
|
335
|
+
"""
|
|
336
|
+
Get CLM components by dimension type.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
dimension: CLM dimension ('abstract', 'concrete', or 'balanced')
|
|
340
|
+
filters: Optional filters
|
|
341
|
+
|
|
342
|
+
Returns:
|
|
343
|
+
List of component information
|
|
344
|
+
"""
|
|
345
|
+
try:
|
|
346
|
+
# Find compatible components
|
|
347
|
+
components = self.clm_assembler.find_compatible_components(
|
|
348
|
+
dimension, filters
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
component_list = []
|
|
352
|
+
for component in components:
|
|
353
|
+
component_list.append(
|
|
354
|
+
{
|
|
355
|
+
"hash": component.mcard_hash,
|
|
356
|
+
"name": component.name,
|
|
357
|
+
"dimension": component.dimension,
|
|
358
|
+
"version": component.version,
|
|
359
|
+
"dependencies": component.dependencies,
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
self.logger.info(f"Found {len(component_list)} {dimension} components")
|
|
364
|
+
|
|
365
|
+
return component_list
|
|
366
|
+
|
|
367
|
+
except (ValueError, TypeError, KeyError, AttributeError) as e:
|
|
368
|
+
self.logger.error(
|
|
369
|
+
f"Failed to get {dimension} components: {str(e)}", exc_info=True
|
|
370
|
+
)
|
|
371
|
+
return []
|
|
372
|
+
|
|
373
|
+
def create_verification_vcard(
|
|
374
|
+
self,
|
|
375
|
+
pcard_hash: str,
|
|
376
|
+
target_hash: str,
|
|
377
|
+
verification_result: dict[str, Any],
|
|
378
|
+
execution_output: Any = None,
|
|
379
|
+
) -> dict[str, Any]:
|
|
380
|
+
"""
|
|
381
|
+
Create a verification VCard as audit evidence.
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
pcard_hash: Hash of the executed PCard
|
|
385
|
+
target_hash: Hash of the target MCard/VCard
|
|
386
|
+
verification_result: CLM verification results
|
|
387
|
+
execution_output: Output from execution
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
Dictionary with VCard creation results
|
|
391
|
+
"""
|
|
392
|
+
try:
|
|
393
|
+
# Create VCard content
|
|
394
|
+
vcard_content = {
|
|
395
|
+
"type": "VerificationVCard",
|
|
396
|
+
"subject": {"pcard_hash": pcard_hash, "target_hash": target_hash},
|
|
397
|
+
"verifier": "ptr_collection_manager",
|
|
398
|
+
"evidence": {
|
|
399
|
+
"clm_verification": verification_result,
|
|
400
|
+
"execution_output": (
|
|
401
|
+
str(execution_output) if execution_output else None
|
|
402
|
+
),
|
|
403
|
+
"verification_timestamp": datetime.now(timezone.utc).isoformat(),
|
|
404
|
+
},
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
# Create metadata
|
|
408
|
+
vcard_metadata = {
|
|
409
|
+
"verification_type": "execution",
|
|
410
|
+
"pcard_hash": pcard_hash,
|
|
411
|
+
"target_hash": target_hash,
|
|
412
|
+
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
# Store VCard
|
|
416
|
+
storage_result = self.storage.store_vcard(vcard_content, vcard_metadata)
|
|
417
|
+
|
|
418
|
+
if not storage_result.success:
|
|
419
|
+
raise ValueError(
|
|
420
|
+
f"Failed to store VCard: {storage_result.error_message}"
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
self.logger.info(f"Created VerificationVCard: {storage_result.hash}")
|
|
424
|
+
|
|
425
|
+
return {
|
|
426
|
+
"success": True,
|
|
427
|
+
"vcard_hash": storage_result.hash,
|
|
428
|
+
"metadata": storage_result.metadata,
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
except (ValueError, TypeError, KeyError) as e:
|
|
432
|
+
self.logger.error(
|
|
433
|
+
f"Failed to create VerificationVCard: {str(e)}", exc_info=True
|
|
434
|
+
)
|
|
435
|
+
return {"success": False, "error_message": str(e)}
|
|
436
|
+
|
|
437
|
+
def get_collection_statistics(self) -> CollectionStats:
|
|
438
|
+
"""
|
|
439
|
+
Get comprehensive statistics for the managed collection.
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
CollectionStats object with detailed statistics
|
|
443
|
+
"""
|
|
444
|
+
try:
|
|
445
|
+
# Get basic storage statistics
|
|
446
|
+
storage_stats = self.storage.get_storage_statistics()
|
|
447
|
+
|
|
448
|
+
# Count CLM components
|
|
449
|
+
clm_component_count = 0
|
|
450
|
+
for dimension in ["abstract", "concrete", "balanced"]:
|
|
451
|
+
components = self.clm_assembler.find_compatible_components(dimension)
|
|
452
|
+
clm_component_count += len(components)
|
|
453
|
+
|
|
454
|
+
# Count assembled CLMs
|
|
455
|
+
assembled_clms = self.clm_assembler.list_assembled_clms()
|
|
456
|
+
assembled_clm_count = len(assembled_clms)
|
|
457
|
+
|
|
458
|
+
# Create stats object
|
|
459
|
+
stats = CollectionStats(
|
|
460
|
+
total_cards=storage_stats.get("total_cards", 0),
|
|
461
|
+
pcard_count=storage_stats.get("by_type", {}).get("pcard", 0),
|
|
462
|
+
vcard_count=storage_stats.get("by_type", {}).get("vcard", 0),
|
|
463
|
+
clm_component_count=clm_component_count,
|
|
464
|
+
assembled_clm_count=assembled_clm_count,
|
|
465
|
+
last_updated=datetime.now(timezone.utc),
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
return stats
|
|
469
|
+
|
|
470
|
+
except (ValueError, TypeError, KeyError, AttributeError) as e:
|
|
471
|
+
self.logger.error(
|
|
472
|
+
f"Failed to get collection statistics: {str(e)}", exc_info=True
|
|
473
|
+
)
|
|
474
|
+
return CollectionStats(
|
|
475
|
+
total_cards=0,
|
|
476
|
+
pcard_count=0,
|
|
477
|
+
vcard_count=0,
|
|
478
|
+
clm_component_count=0,
|
|
479
|
+
assembled_clm_count=0,
|
|
480
|
+
last_updated=datetime.now(timezone.utc),
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
def search_collection(
|
|
484
|
+
self, query: str, card_type: str = "all"
|
|
485
|
+
) -> list[dict[str, Any]]:
|
|
486
|
+
"""
|
|
487
|
+
Search across the entire collection.
|
|
488
|
+
|
|
489
|
+
Args:
|
|
490
|
+
query: Search query
|
|
491
|
+
card_type: Type of cards to search ('all', 'pcard', 'vcard', 'component')
|
|
492
|
+
|
|
493
|
+
Returns:
|
|
494
|
+
List of search results
|
|
495
|
+
"""
|
|
496
|
+
try:
|
|
497
|
+
all_results = []
|
|
498
|
+
|
|
499
|
+
if card_type in ["all", "pcard"]:
|
|
500
|
+
pcard_results = self.storage.search_pcards(query)
|
|
501
|
+
for result in pcard_results:
|
|
502
|
+
if result.success:
|
|
503
|
+
all_results.append(
|
|
504
|
+
{
|
|
505
|
+
"type": "pcard",
|
|
506
|
+
"hash": result.metadata.get("hash", "unknown"),
|
|
507
|
+
"name": result.metadata.get("name", "unnamed"),
|
|
508
|
+
"metadata": result.metadata,
|
|
509
|
+
}
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
if card_type in ["all", "vcard"]:
|
|
513
|
+
vcard_results = self.storage.search_vcards(query)
|
|
514
|
+
for result in vcard_results:
|
|
515
|
+
if result.success:
|
|
516
|
+
all_results.append(
|
|
517
|
+
{
|
|
518
|
+
"type": "vcard",
|
|
519
|
+
"hash": result.metadata.get("hash", "unknown"),
|
|
520
|
+
"verification_type": result.metadata.get(
|
|
521
|
+
"verification_type", "unknown"
|
|
522
|
+
),
|
|
523
|
+
"metadata": result.metadata,
|
|
524
|
+
}
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
if card_type in ["all", "component"]:
|
|
528
|
+
# Search for CLM components
|
|
529
|
+
for dimension in ["abstract", "concrete", "balanced"]:
|
|
530
|
+
components = self.clm_assembler.find_compatible_components(
|
|
531
|
+
dimension
|
|
532
|
+
)
|
|
533
|
+
for component in components:
|
|
534
|
+
if query.lower() in component.name.lower():
|
|
535
|
+
all_results.append(
|
|
536
|
+
{
|
|
537
|
+
"type": "component",
|
|
538
|
+
"dimension": dimension,
|
|
539
|
+
"hash": component.mcard_hash,
|
|
540
|
+
"name": component.name,
|
|
541
|
+
"version": component.version,
|
|
542
|
+
}
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
self.logger.info(
|
|
546
|
+
f"Search for '{query}' found {len(all_results)} results (type: {card_type})"
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
return all_results
|
|
550
|
+
|
|
551
|
+
except (ValueError, TypeError, KeyError, AttributeError) as e:
|
|
552
|
+
self.logger.error(f"Failed to search collection: {str(e)}", exc_info=True)
|
|
553
|
+
return []
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""CLM Layer 4 Universal Subcommand Grammar Registry and Dispatcher.
|
|
2
|
+
|
|
3
|
+
Sprint 412 / DEL-412-04.
|
|
4
|
+
Normative Spec: docs/spec/30-interfaces/universal_subcommand_grammar.md
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
|
|
12
|
+
from clm.layer4.commands.action_cmd import action_cmd, workflow_cmd
|
|
13
|
+
from clm.layer4.commands.check_cmd import check_cmd
|
|
14
|
+
from clm.layer4.commands.envelope import format_error, format_failure, format_success
|
|
15
|
+
from clm.layer4.commands.evaluate_cmd import (
|
|
16
|
+
assess_equivalence_subcmd,
|
|
17
|
+
compose_conditions_subcmd,
|
|
18
|
+
directory_fs_scan_subcmd,
|
|
19
|
+
directory_to_db_subcmd,
|
|
20
|
+
evaluate_subcmd,
|
|
21
|
+
remote_handle_resolver_subcmd,
|
|
22
|
+
route_handle_subcmd,
|
|
23
|
+
)
|
|
24
|
+
from clm.layer4.commands.mcard_cmd import mcard_cmd
|
|
25
|
+
from clm.layer4.commands.petri_cmd import petri_run_net_cmd
|
|
26
|
+
from clm.layer4.commands.tridb_cmd import (
|
|
27
|
+
init_tridb_cmd,
|
|
28
|
+
memorize_mcard_cmd,
|
|
29
|
+
register_handle_cmd,
|
|
30
|
+
resolve_handle_cmd,
|
|
31
|
+
resolve_handle_hash_cmd,
|
|
32
|
+
sql_cmd,
|
|
33
|
+
)
|
|
34
|
+
from clm.layer4.commands.version_cmd import version_cmd
|
|
35
|
+
|
|
36
|
+
# Registry mapping all USG and backward-compatible subcommands to their handlers
|
|
37
|
+
COMMAND_REGISTRY: dict[str, Callable[[list[str]], int]] = {
|
|
38
|
+
# 12 Canonical USG Subcommands
|
|
39
|
+
"evaluate": evaluate_subcmd,
|
|
40
|
+
"petri-run-net": petri_run_net_cmd,
|
|
41
|
+
"run-net": petri_run_net_cmd, # Alias
|
|
42
|
+
"init-tridb": init_tridb_cmd,
|
|
43
|
+
"memorize-mcard": memorize_mcard_cmd,
|
|
44
|
+
"resolve-handle": resolve_handle_cmd,
|
|
45
|
+
"sql": sql_cmd,
|
|
46
|
+
"mcard": mcard_cmd,
|
|
47
|
+
"compose-conditions": compose_conditions_subcmd,
|
|
48
|
+
"action": action_cmd,
|
|
49
|
+
"workflow": workflow_cmd,
|
|
50
|
+
"check": check_cmd,
|
|
51
|
+
"version": version_cmd,
|
|
52
|
+
# Extended & Backward-Compatibility Commands
|
|
53
|
+
"resolve-handle-hash": resolve_handle_hash_cmd,
|
|
54
|
+
"register-handle": register_handle_cmd,
|
|
55
|
+
"assess-equivalence": assess_equivalence_subcmd,
|
|
56
|
+
"directory-fs-scan": directory_fs_scan_subcmd,
|
|
57
|
+
"directory-to-db": directory_to_db_subcmd,
|
|
58
|
+
"route-handle": route_handle_subcmd,
|
|
59
|
+
"remote-handle-resolver": remote_handle_resolver_subcmd,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
KNOWN_COMMANDS: set[str] = set(COMMAND_REGISTRY.keys())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def dispatch_command(command: str, args: list[str]) -> int:
|
|
66
|
+
"""Dispatch a command string and arguments to its registered handler."""
|
|
67
|
+
handler = COMMAND_REGISTRY.get(command)
|
|
68
|
+
if handler is None:
|
|
69
|
+
print(f"Unknown command: {command}", file=sys.stderr)
|
|
70
|
+
return 1
|
|
71
|
+
return handler(args)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
__all__ = [
|
|
75
|
+
"COMMAND_REGISTRY",
|
|
76
|
+
"KNOWN_COMMANDS",
|
|
77
|
+
"dispatch_command",
|
|
78
|
+
"format_success",
|
|
79
|
+
"format_failure",
|
|
80
|
+
"format_error",
|
|
81
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Action and Workflow Subcommand Handlers.
|
|
2
|
+
|
|
3
|
+
Sprint 412 / DEL-412-04.
|
|
4
|
+
Normative Spec: docs/spec/30-interfaces/universal_subcommand_grammar.md §2.9 - §2.10
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
from clm.layer4.action_commands import handle_action_cli, handle_workflow_cli
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def action_cmd(args: list[str]) -> int:
|
|
15
|
+
"""Handle 'action' subcommand."""
|
|
16
|
+
if "--help" in args or "-h" in args:
|
|
17
|
+
print("Usage: clm action <apply|run|validate|diff|list> <spec.yaml> [options]")
|
|
18
|
+
return 0
|
|
19
|
+
|
|
20
|
+
if not args:
|
|
21
|
+
print("Usage: clm action <apply|run|validate|diff|list> <spec.yaml> [options]", file=sys.stderr)
|
|
22
|
+
return 2
|
|
23
|
+
|
|
24
|
+
# Translate USG 'apply' to existing 'run' subcommand
|
|
25
|
+
translated = list(args)
|
|
26
|
+
if translated and translated[0] == "apply":
|
|
27
|
+
translated[0] = "run"
|
|
28
|
+
|
|
29
|
+
return handle_action_cli(translated)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def workflow_cmd(args: list[str]) -> int:
|
|
33
|
+
"""Handle 'workflow' subcommand."""
|
|
34
|
+
if "--help" in args or "-h" in args:
|
|
35
|
+
print("Usage: clm workflow <run|validate|status> <dag.yaml> [options]")
|
|
36
|
+
return 0
|
|
37
|
+
|
|
38
|
+
if not args:
|
|
39
|
+
print("Usage: clm workflow <run|validate|status> <dag.yaml> [options]", file=sys.stderr)
|
|
40
|
+
return 2
|
|
41
|
+
|
|
42
|
+
return handle_workflow_cli(args)
|