domainforge 0.13.0
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.
- package/.cargo/config.toml +6 -0
- package/.claude/settings.local.json +18 -0
- package/.coderabbit.yml +43 -0
- package/.codex/skills/release-management/SKILL.md +151 -0
- package/.codex/skills/release-management/agents/openai.yaml +4 -0
- package/.github/actions/decrypt-secrets/action.yml +121 -0
- package/.github/agents/Coder.agent.md +97 -0
- package/.github/agents/DeepResearch.agent.md +61 -0
- package/.github/chatmodes/tdd.vibepro.chatmode.md +1183 -0
- package/.github/copilot-instructions.md +13 -0
- package/.github/dependabot.yml +68 -0
- package/.github/workflows/README.md +165 -0
- package/.github/workflows/ci.yml +335 -0
- package/.github/workflows/dependabot-automerge.yml +114 -0
- package/.github/workflows/dependency-review.yml +27 -0
- package/.github/workflows/deploy.yml +87 -0
- package/.github/workflows/prepare-release.yml +168 -0
- package/.github/workflows/release-crates.yml +42 -0
- package/.github/workflows/release-npm.yml +137 -0
- package/.github/workflows/release-please.yml +29 -0
- package/.github/workflows/release-pypi.yml +96 -0
- package/.gitkeep +1 -0
- package/.release-please-manifest.json +5 -0
- package/.sea-registry.toml +10 -0
- package/.serena/project.yml +133 -0
- package/.sops.yaml +10 -0
- package/AGENTS.md +216 -0
- package/CHANGELOG.md +400 -0
- package/CLAUDE.md +62 -0
- package/CONTRIBUTING.md +323 -0
- package/Cargo.lock +3612 -0
- package/Cargo.toml +12 -0
- package/LICENSE +201 -0
- package/README.md +660 -0
- package/README_PYTHON.md +256 -0
- package/README_TYPESCRIPT.md +305 -0
- package/README_WASM.md +329 -0
- package/RELEASE_NOTES.md +41 -0
- package/bun.lock +378 -0
- package/bunfig.toml +11 -0
- package/check_output.txt +83 -0
- package/clippy_output.txt +80 -0
- package/commitlint.config.cjs +8 -0
- package/deny.toml +42 -0
- package/devbox.json +14 -0
- package/devbox.lock +76 -0
- package/docs/RELEASE_PROCESS.md +360 -0
- package/docs/diagnostics.md +161 -0
- package/docs/doc_guidelines.md +53 -0
- package/docs/explanations/README.md +21 -0
- package/docs/explanations/architecture-overview.md +109 -0
- package/docs/explanations/cross-language-binding-strategy.md +68 -0
- package/docs/explanations/graph-store-design.md +47 -0
- package/docs/explanations/performance-benchmarks.md +63 -0
- package/docs/explanations/policy-evaluation-logic.md +106 -0
- package/docs/explanations/semantic-modeling-concepts.md +109 -0
- package/docs/explanations/three-valued-logic.md +66 -0
- package/docs/explanations/versioning-strategy.md +45 -0
- package/docs/governance.md +168 -0
- package/docs/how-tos/README.md +46 -0
- package/docs/how-tos/ci-cd-validation.md +93 -0
- package/docs/how-tos/create-custom-units.md +125 -0
- package/docs/how-tos/define-policies.md +119 -0
- package/docs/how-tos/export-to-calm.md +110 -0
- package/docs/how-tos/export-to-protobuf.md +312 -0
- package/docs/how-tos/extend-grammar.md +133 -0
- package/docs/how-tos/generate-rdf-turtle.md +106 -0
- package/docs/how-tos/import-from-calm.md +114 -0
- package/docs/how-tos/import-from-sbvr.md +249 -0
- package/docs/how-tos/install-cli.md +126 -0
- package/docs/how-tos/parse-sea-files.md +132 -0
- package/docs/how-tos/policy-evaluation-modes.md +30 -0
- package/docs/how-tos/run-cross-language-tests.md +115 -0
- package/docs/how-tos/troubleshoot-napi-builds.md +55 -0
- package/docs/how-tos/use-modules-imports.md +285 -0
- package/docs/index.md +13 -0
- package/docs/plans/canonical-normalizer.md +121 -0
- package/docs/plans/cd_improvement.md +112 -0
- package/docs/plans/cli-ast.md +29 -0
- package/docs/plans/expression-bindings-and-normalizer-integration.md +174 -0
- package/docs/plans/protobuf_advanced_features_plan.md +597 -0
- package/docs/plans/protobuf_plan.yml +525 -0
- package/docs/plans/refactor_dsl_architecture.md +131 -0
- package/docs/plans/release-plan.md +163 -0
- package/docs/plans/sea_fmt_implementation_plan.md +516 -0
- package/docs/playbooks/README.md +18 -0
- package/docs/playbooks/adding-new-primitive.md +68 -0
- package/docs/playbooks/debugging-parser-failures.md +42 -0
- package/docs/playbooks/local-release-preparation.md +139 -0
- package/docs/playbooks/migrating-schema-versions.md +43 -0
- package/docs/playbooks/onboarding-contributors.md +64 -0
- package/docs/playbooks/releasing-beta.md +86 -0
- package/docs/playbooks/secret-management.md +64 -0
- package/docs/reference/README.md +199 -0
- package/docs/reference/ast-json-api.md +427 -0
- package/docs/reference/calm-mapping.md +519 -0
- package/docs/reference/cli-commands.md +588 -0
- package/docs/reference/configuration.md +202 -0
- package/docs/reference/error-codes.md +664 -0
- package/docs/reference/generated-artifacts-policy.md +53 -0
- package/docs/reference/grammar-spec.md +255 -0
- package/docs/reference/primitives-api.md +317 -0
- package/docs/reference/protobuf-api.md +426 -0
- package/docs/reference/python-api.md +485 -0
- package/docs/reference/registry.md +50 -0
- package/docs/reference/sea-dsl-ai-cheatsheet.yaml +913 -0
- package/docs/reference/security-model.md +74 -0
- package/docs/reference/typescript-api.md +508 -0
- package/docs/reference/wasm-api.md +420 -0
- package/docs/semantic-pack-review.md +144 -0
- package/docs/semantic-pack-signing.md +234 -0
- package/docs/semantic-packs.md +284 -0
- package/docs/specs/ADR-001-sea-dsl-semantic-source-of-truth.md +33 -0
- package/docs/specs/ADR-002-projection-first-class-construct.md +50 -0
- package/docs/specs/ADR-003-protobuf-projection-target.md +51 -0
- package/docs/specs/ADR-004-projection-compatibility-semantics.md +57 -0
- package/docs/specs/ADR-005-multi-language-support-strategy.md +112 -0
- package/docs/specs/ADR-006-error-handling-strategy.md +115 -0
- package/docs/specs/ADR-007-policy-evaluation-engine.md +95 -0
- package/docs/specs/ADR-008-knowledge-graph-integration.md +90 -0
- package/docs/specs/ADR-009-module-resolution-strategy.md +115 -0
- package/docs/specs/ADR-010-unit-system.md +106 -0
- package/docs/specs/PRD-001-sea-projection-framework.md +155 -0
- package/docs/specs/PRD-002-sea-cli-tooling.md +169 -0
- package/docs/specs/PRD-003-dsl-core-capabilities.md +275 -0
- package/docs/specs/README.md +62 -0
- package/docs/specs/SDS-001-protobuf-projection-engine.md +451 -0
- package/docs/specs/SDS-002-sea-core-architecture.md +268 -0
- package/docs/specs/SDS-003-parser-semantic-graph.md +377 -0
- package/docs/specs/SDS-004-policy-engine-design.md +362 -0
- package/docs/specs/SDS-005-knowledge-graph-module.md +364 -0
- package/docs/specs/SDS-006-calm-integration.md +367 -0
- package/docs/specs/SDS-007-sbvr-import.md +347 -0
- package/docs/templates/template_explanation.md +14 -0
- package/docs/templates/template_howto.md +21 -0
- package/docs/templates/template_playbook.md +21 -0
- package/docs/templates/template_reference.md +17 -0
- package/docs/templates/template_tutorial.md +24 -0
- package/docs/tutorials/README.md +12 -0
- package/docs/tutorials/first-sea-model.md +85 -0
- package/docs/tutorials/getting-started.md +98 -0
- package/docs/tutorials/python-binding-quickstart.md +107 -0
- package/docs/tutorials/typescript-binding-quickstart.md +91 -0
- package/docs/tutorials/wasm-in-browser.md +75 -0
- package/domainforge-core/CHANGELOG.md +138 -0
- package/domainforge-core/Cargo.toml +101 -0
- package/domainforge-core/MIGRATING.md +32 -0
- package/domainforge-core/README.md +197 -0
- package/domainforge-core/benchmark_results.txt +51 -0
- package/domainforge-core/build.rs +6 -0
- package/domainforge-core/deny.toml +31 -0
- package/domainforge-core/docs/specs/projections/sbvr_kg_mapping.md +43 -0
- package/domainforge-core/examples/basic.sea +7 -0
- package/domainforge-core/examples/cli/import_export_workflow.sh +38 -0
- package/domainforge-core/examples/cli/validate_example.sh +30 -0
- package/domainforge-core/examples/evolution_semantics.sea +31 -0
- package/domainforge-core/examples/parser_demo.rs +203 -0
- package/domainforge-core/grammar/sea.pest +408 -0
- package/domainforge-core/schemas/calm-v1.schema.json +170 -0
- package/domainforge-core/schemas/shacl/sea_shapes.ttl +19 -0
- package/domainforge-core/src/authority/compiler.rs +309 -0
- package/domainforge-core/src/authority/environment.rs +203 -0
- package/domainforge-core/src/authority/error.rs +164 -0
- package/domainforge-core/src/authority/fact_resolver.rs +224 -0
- package/domainforge-core/src/authority/mod.rs +25 -0
- package/domainforge-core/src/authority/pack.rs +133 -0
- package/domainforge-core/src/authority/policy.rs +224 -0
- package/domainforge-core/src/authority/resolver.rs +446 -0
- package/domainforge-core/src/authority/trace.rs +217 -0
- package/domainforge-core/src/authority/transform.rs +168 -0
- package/domainforge-core/src/authority/types.rs +617 -0
- package/domainforge-core/src/bin/domainforge.rs +25 -0
- package/domainforge-core/src/calm/export.rs +538 -0
- package/domainforge-core/src/calm/import.rs +1220 -0
- package/domainforge-core/src/calm/mod.rs +9 -0
- package/domainforge-core/src/calm/models.rs +108 -0
- package/domainforge-core/src/calm/sbvr_import.rs +9 -0
- package/domainforge-core/src/cli/authority.rs +149 -0
- package/domainforge-core/src/cli/format.rs +85 -0
- package/domainforge-core/src/cli/import.rs +133 -0
- package/domainforge-core/src/cli/mod.rs +64 -0
- package/domainforge-core/src/cli/normalize.rs +180 -0
- package/domainforge-core/src/cli/pack.rs +904 -0
- package/domainforge-core/src/cli/parse.rs +112 -0
- package/domainforge-core/src/cli/project.rs +294 -0
- package/domainforge-core/src/cli/registry.rs +41 -0
- package/domainforge-core/src/cli/test.rs +12 -0
- package/domainforge-core/src/cli/validate.rs +195 -0
- package/domainforge-core/src/cli/validate_kg.rs +80 -0
- package/domainforge-core/src/concept_id.rs +89 -0
- package/domainforge-core/src/error/diagnostics.rs +426 -0
- package/domainforge-core/src/error/fuzzy.rs +253 -0
- package/domainforge-core/src/error/mod.rs +13 -0
- package/domainforge-core/src/formatter/comments.rs +223 -0
- package/domainforge-core/src/formatter/config.rs +114 -0
- package/domainforge-core/src/formatter/mod.rs +22 -0
- package/domainforge-core/src/formatter/printer.rs +906 -0
- package/domainforge-core/src/graph/mod.rs +858 -0
- package/domainforge-core/src/graph/to_ast.rs +66 -0
- package/domainforge-core/src/kg.rs +1476 -0
- package/domainforge-core/src/kg_import.rs +251 -0
- package/domainforge-core/src/lib.rs +203 -0
- package/domainforge-core/src/module/mod.rs +1 -0
- package/domainforge-core/src/module/resolver.rs +260 -0
- package/domainforge-core/src/parser/ast.rs +2919 -0
- package/domainforge-core/src/parser/ast_convert.rs +494 -0
- package/domainforge-core/src/parser/ast_schema.rs +491 -0
- package/domainforge-core/src/parser/error.rs +291 -0
- package/domainforge-core/src/parser/lint.rs +39 -0
- package/domainforge-core/src/parser/mod.rs +193 -0
- package/domainforge-core/src/parser/printer.rs +702 -0
- package/domainforge-core/src/parser/profiles.rs +71 -0
- package/domainforge-core/src/parser/string_utils.rs +138 -0
- package/domainforge-core/src/patterns.rs +68 -0
- package/domainforge-core/src/policy/core.rs +1148 -0
- package/domainforge-core/src/policy/expression.rs +399 -0
- package/domainforge-core/src/policy/mod.rs +18 -0
- package/domainforge-core/src/policy/normalize.rs +1028 -0
- package/domainforge-core/src/policy/quantifier.rs +940 -0
- package/domainforge-core/src/policy/three_valued.rs +140 -0
- package/domainforge-core/src/policy/three_valued_microbench.rs +104 -0
- package/domainforge-core/src/policy/type_inference.rs +67 -0
- package/domainforge-core/src/policy/violation.rs +36 -0
- package/domainforge-core/src/primitives/concept_change.rs +61 -0
- package/domainforge-core/src/primitives/entity.rs +224 -0
- package/domainforge-core/src/primitives/flow.rs +111 -0
- package/domainforge-core/src/primitives/instance.rs +93 -0
- package/domainforge-core/src/primitives/mapping_contract.rs +50 -0
- package/domainforge-core/src/primitives/metric.rs +79 -0
- package/domainforge-core/src/primitives/mod.rs +25 -0
- package/domainforge-core/src/primitives/projection_contract.rs +50 -0
- package/domainforge-core/src/primitives/quantity.rs +56 -0
- package/domainforge-core/src/primitives/relation.rs +68 -0
- package/domainforge-core/src/primitives/resource.rs +237 -0
- package/domainforge-core/src/primitives/resource_instance.rs +88 -0
- package/domainforge-core/src/primitives/role.rs +49 -0
- package/domainforge-core/src/projection/buf.rs +404 -0
- package/domainforge-core/src/projection/contracts.rs +22 -0
- package/domainforge-core/src/projection/engine.rs +19 -0
- package/domainforge-core/src/projection/mod.rs +16 -0
- package/domainforge-core/src/projection/protobuf.rs +3331 -0
- package/domainforge-core/src/projection/registry.rs +43 -0
- package/domainforge-core/src/python/authority.rs +253 -0
- package/domainforge-core/src/python/error.rs +227 -0
- package/domainforge-core/src/python/formatter.rs +86 -0
- package/domainforge-core/src/python/graph.rs +366 -0
- package/domainforge-core/src/python/mod.rs +9 -0
- package/domainforge-core/src/python/policy.rs +651 -0
- package/domainforge-core/src/python/primitives.rs +796 -0
- package/domainforge-core/src/python/registry.rs +98 -0
- package/domainforge-core/src/python/semantic_pack.rs +619 -0
- package/domainforge-core/src/python/units.rs +96 -0
- package/domainforge-core/src/registry/mod.rs +432 -0
- package/domainforge-core/src/registry/tests.rs +210 -0
- package/domainforge-core/src/sbvr.rs +744 -0
- package/domainforge-core/src/semantic_pack/builder.rs +470 -0
- package/domainforge-core/src/semantic_pack/canonical_json.rs +184 -0
- package/domainforge-core/src/semantic_pack/diagnostics.rs +214 -0
- package/domainforge-core/src/semantic_pack/diff.rs +216 -0
- package/domainforge-core/src/semantic_pack/mod.rs +31 -0
- package/domainforge-core/src/semantic_pack/pack_set.rs +240 -0
- package/domainforge-core/src/semantic_pack/resolver.rs +437 -0
- package/domainforge-core/src/semantic_pack/review.rs +125 -0
- package/domainforge-core/src/semantic_pack/schema.rs +342 -0
- package/domainforge-core/src/semantic_pack/signing.rs +105 -0
- package/domainforge-core/src/semantic_pack/validator.rs +368 -0
- package/domainforge-core/src/semantic_version.rs +140 -0
- package/domainforge-core/src/test_utils.rs +12 -0
- package/domainforge-core/src/typescript/authority.rs +184 -0
- package/domainforge-core/src/typescript/error.rs +146 -0
- package/domainforge-core/src/typescript/formatter.rs +76 -0
- package/domainforge-core/src/typescript/graph.rs +391 -0
- package/domainforge-core/src/typescript/mod.rs +9 -0
- package/domainforge-core/src/typescript/policy.rs +564 -0
- package/domainforge-core/src/typescript/primitives.rs +784 -0
- package/domainforge-core/src/typescript/registry.rs +88 -0
- package/domainforge-core/src/typescript/semantic_pack.rs +470 -0
- package/domainforge-core/src/typescript/units.rs +76 -0
- package/domainforge-core/src/units/mod.rs +462 -0
- package/domainforge-core/src/uuid_module.rs +42 -0
- package/domainforge-core/src/validation_error.rs +818 -0
- package/domainforge-core/src/validation_result.rs +30 -0
- package/domainforge-core/src/wasm/authority.rs +192 -0
- package/domainforge-core/src/wasm/error.rs +145 -0
- package/domainforge-core/src/wasm/formatter.rs +69 -0
- package/domainforge-core/src/wasm/graph.rs +471 -0
- package/domainforge-core/src/wasm/mod.rs +16 -0
- package/domainforge-core/src/wasm/policy.rs +607 -0
- package/domainforge-core/src/wasm/primitives.rs +295 -0
- package/domainforge-core/src/wasm/semantic_pack.rs +471 -0
- package/domainforge-core/src/wasm/units.rs +62 -0
- package/domainforge-core/std/aws.sea +6 -0
- package/domainforge-core/std/core.sea +6 -0
- package/domainforge-core/std/http.sea +27 -0
- package/domainforge-core/tests/aggregation_enhanced_tests.rs +162 -0
- package/domainforge-core/tests/aggregation_eval_tests.rs +248 -0
- package/domainforge-core/tests/aggregation_integration_tests.rs +379 -0
- package/domainforge-core/tests/aggregation_parser_tests.rs +92 -0
- package/domainforge-core/tests/aggregation_tests.rs +102 -0
- package/domainforge-core/tests/authority_conformance_tests.rs +1173 -0
- package/domainforge-core/tests/calm_round_trip_tests.rs +283 -0
- package/domainforge-core/tests/calm_schema_validation_tests.rs +137 -0
- package/domainforge-core/tests/cast_operator_tests.rs +85 -0
- package/domainforge-core/tests/cli_binary_check.rs +37 -0
- package/domainforge-core/tests/cli_import_tests.rs +291 -0
- package/domainforge-core/tests/cli_path_traversal_tests.rs +124 -0
- package/domainforge-core/tests/cli_tests.rs +63 -0
- package/domainforge-core/tests/diagnostics_tests.rs +203 -0
- package/domainforge-core/tests/dimension_unit_tests.rs +80 -0
- package/domainforge-core/tests/entity_tests.rs +69 -0
- package/domainforge-core/tests/evolution_semantics_tests.rs +157 -0
- package/domainforge-core/tests/flow_tests.rs +78 -0
- package/domainforge-core/tests/flow_unit_validation_tests.rs +31 -0
- package/domainforge-core/tests/graph_integration_tests.rs +218 -0
- package/domainforge-core/tests/graph_tests.rs +626 -0
- package/domainforge-core/tests/import_parsing_tests.rs +23 -0
- package/domainforge-core/tests/instance_integration_tests.rs +98 -0
- package/domainforge-core/tests/instance_parsing_tests.rs +58 -0
- package/domainforge-core/tests/instance_tests.rs +61 -0
- package/domainforge-core/tests/kg_uri_encoding_tests.rs +53 -0
- package/domainforge-core/tests/lint_tests.rs +19 -0
- package/domainforge-core/tests/metric_tests.rs +143 -0
- package/domainforge-core/tests/module_resolution_tests.rs +100 -0
- package/domainforge-core/tests/namespace_registry_tests.rs +247 -0
- package/domainforge-core/tests/null_handling_tests.rs +26 -0
- package/domainforge-core/tests/parser_ast_v3.rs +53 -0
- package/domainforge-core/tests/parser_dimension_registry_tests.rs +20 -0
- package/domainforge-core/tests/parser_integration_tests.rs +294 -0
- package/domainforge-core/tests/parser_metadata_tests.rs +97 -0
- package/domainforge-core/tests/parser_resource_domain_only_graph_test.rs +21 -0
- package/domainforge-core/tests/parser_resource_limits_tests.rs +122 -0
- package/domainforge-core/tests/parser_tests.rs +512 -0
- package/domainforge-core/tests/pattern_semantics_tests.rs +87 -0
- package/domainforge-core/tests/phase_14_determinism_tests.rs +166 -0
- package/domainforge-core/tests/phase_15_validation_error_tests.rs +136 -0
- package/domainforge-core/tests/phase_16_unicode_tests.rs +248 -0
- package/domainforge-core/tests/phase_17_export_tests.rs +285 -0
- package/domainforge-core/tests/phase_17_round_trip_tests.rs +264 -0
- package/domainforge-core/tests/policy_tests.rs +635 -0
- package/domainforge-core/tests/primitives_integration_tests.rs +151 -0
- package/domainforge-core/tests/print_rdf_xml.rs +14 -0
- package/domainforge-core/tests/printer_tests.rs +204 -0
- package/domainforge-core/tests/profile_tests.rs +35 -0
- package/domainforge-core/tests/projection_contracts_tests.rs +154 -0
- package/domainforge-core/tests/protobuf_projection_tests.rs +199 -0
- package/domainforge-core/tests/quantity_tests.rs +41 -0
- package/domainforge-core/tests/rdf_xml_typed_literal_tests.rs +105 -0
- package/domainforge-core/tests/registry_schema_tests.rs +33 -0
- package/domainforge-core/tests/resource_tests.rs +50 -0
- package/domainforge-core/tests/resource_unit_tests.rs +24 -0
- package/domainforge-core/tests/roles_relations_tests.rs +61 -0
- package/domainforge-core/tests/round_trip_tests.rs +34 -0
- package/domainforge-core/tests/runtime_toggle_tests.rs +70 -0
- package/domainforge-core/tests/sbvr_fact_schema_tests.rs +60 -0
- package/domainforge-core/tests/sbvr_flow_facts_tests.rs +55 -0
- package/domainforge-core/tests/sbvr_parsing_tests.rs +53 -0
- package/domainforge-core/tests/semantic_pack_alias_resolution.rs +197 -0
- package/domainforge-core/tests/semantic_pack_build.rs +302 -0
- package/domainforge-core/tests/semantic_pack_consumer_smoke.rs +150 -0
- package/domainforge-core/tests/semantic_pack_pack_set.rs +160 -0
- package/domainforge-core/tests/semantic_pack_signing.rs +157 -0
- package/domainforge-core/tests/semantic_pack_three_valued.rs +250 -0
- package/domainforge-core/tests/semantic_pack_validate.rs +196 -0
- package/domainforge-core/tests/std_lib_tests.rs +37 -0
- package/domainforge-core/tests/temporal_evaluation_tests.rs +159 -0
- package/domainforge-core/tests/temporal_semantics_tests.rs +214 -0
- package/domainforge-core/tests/three_valued_quantifiers_tests.rs +164 -0
- package/domainforge-core/tests/turtle_entity_export_tests.rs +38 -0
- package/domainforge-core/tests/turtle_escaping_tests.rs +53 -0
- package/domainforge-core/tests/turtle_resource_export_tests.rs +34 -0
- package/domainforge-core/tests/type_inference_tests.rs +40 -0
- package/domainforge-core/tests/unicode_validation_tests.rs +169 -0
- package/domainforge-core/tests/unit_tests.rs +81 -0
- package/domainforge-core/tests/validate_tests.rs +38 -0
- package/domainforge-core/tests/validation_unit_mismatch_tests.rs +83 -0
- package/domainforge-core/tests/wasm_tests.rs +229 -0
- package/domainforge-python/CHANGELOG-python.md +12 -0
- package/domainforge-python/MIGRATING.md +24 -0
- package/domainforge-python/README.md +256 -0
- package/domainforge-python/domainforge/__init__.py +95 -0
- package/domainforge-python/domainforge/domainforge.pyi +519 -0
- package/domainforge-python/pyproject.toml +36 -0
- package/domainforge-typescript/CHANGELOG-typescript.md +12 -0
- package/domainforge-typescript/LICENSE +201 -0
- package/domainforge-typescript/MIGRATING.md +24 -0
- package/domainforge-typescript/README.md +305 -0
- package/domainforge-typescript/index.d.ts +452 -0
- package/domainforge-typescript/index.js +361 -0
- package/domainforge-typescript/package.json +60 -0
- package/example.js +61 -0
- package/examples/browser.html +366 -0
- package/examples/namespaces/finance/cashflow.sea +5 -0
- package/examples/namespaces/logistics/core.sea +7 -0
- package/examples/observability_metrics.sea +38 -0
- package/fixtures/semantic_packs/acme_procurement/domain/entities.sea +39 -0
- package/fixtures/semantic_packs/acme_procurement/domain/metrics.sea +11 -0
- package/fixtures/semantic_packs/acme_procurement/domain/relations.sea +7 -0
- package/fixtures/semantic_packs/acme_procurement/domain/resources.sea +9 -0
- package/fixtures/semantic_packs/acme_procurement/review/acme.procurement.semantic-review.jsonl +7 -0
- package/fixtures/semantic_packs/acme_procurement/tests/ambiguous_vendor_alias.sea +8 -0
- package/fixtures/semantic_packs/acme_procurement/tests/deprecated_vendor_alias.sea +8 -0
- package/fixtures/semantic_packs/acme_procurement/tests/invalid_relation.sea +3 -0
- package/fixtures/semantic_packs/acme_procurement/tests/proposed_concept.sea +8 -0
- package/fixtures/semantic_packs/acme_procurement/tests/rejected_concept.sea +8 -0
- package/fixtures/semantic_packs/acme_procurement/tests/unit_mismatch.sea +7 -0
- package/fixtures/semantic_packs/acme_procurement/tests/unknown_vendor_policy.sea +8 -0
- package/fixtures/semantic_packs/acme_procurement/tests/valid_purchase_policy.sea +8 -0
- package/index.d.ts +2 -0
- package/index.js +8 -0
- package/justfile +200 -0
- package/lefthook.yml +13 -0
- package/lib/validate_native_exports.d.ts +4 -0
- package/lib/validate_native_exports.js +12 -0
- package/package.json +22 -0
- package/pytest.ini +5 -0
- package/python/tests/test_registry.py +75 -0
- package/python/tests/test_units.py +18 -0
- package/release-please-config.json +49 -0
- package/requirements-dev.txt +3 -0
- package/requirements.txt +3 -0
- package/rust-toolchain.toml +3 -0
- package/schemas/ast-v1.schema.json +72 -0
- package/schemas/ast-v2.schema.json +1200 -0
- package/schemas/ast-v3.schema.json +1200 -0
- package/schemas/sea-registry.schema.json +45 -0
- package/scripts/build-python.sh +37 -0
- package/scripts/build-release.sh +279 -0
- package/scripts/build-typescript.sh +13 -0
- package/scripts/build-wasm.sh +113 -0
- package/scripts/bump-version.sh +245 -0
- package/scripts/check_unused_test_imports.py +85 -0
- package/scripts/ci_tasks.py +379 -0
- package/scripts/clear_debug_test.sh +10 -0
- package/scripts/create-github-release.sh +262 -0
- package/scripts/create-tag.sh +203 -0
- package/scripts/find_and_link_test_binary.sh +70 -0
- package/scripts/generate-changelog.sh +271 -0
- package/scripts/generate-release-notes.sh +205 -0
- package/scripts/lint_release_security.py +96 -0
- package/scripts/lint_release_workflows.py +82 -0
- package/scripts/lint_workflow_gates.py +113 -0
- package/scripts/optimized-wasm-build.sh +61 -0
- package/scripts/patch_napi_types.py +62 -0
- package/scripts/pre-release-check.sh +289 -0
- package/scripts/prepare_rust_debug.sh +52 -0
- package/scripts/release.sh +373 -0
- package/scripts/resolve_rust_binary.py +230 -0
- package/scripts/run_commitlint.sh +29 -0
- package/scripts/test-all.sh +77 -0
- package/scripts/update_launch_program.py +93 -0
- package/secrets/README.md +27 -0
- package/secrets/secrets.yaml +21 -0
- package/test_integration.py +67 -0
- package/tests/test_authority.py +328 -0
- package/tests/test_ci_tasks.py +143 -0
- package/tests/test_expression.py +256 -0
- package/tests/test_golden_payment_flow.py +42 -0
- package/tests/test_graph.py +127 -0
- package/tests/test_instance.py +136 -0
- package/tests/test_parser.py +82 -0
- package/tests/test_primitives.py +68 -0
- package/tests/test_role_relation_parity.py +56 -0
- package/tests/test_runtime_toggle.py +156 -0
- package/tests/test_semantic_pack.py +639 -0
- package/tests/test_three_valued_eval.py +159 -0
- package/tsconfig.json +30 -0
- package/typescript-tests/advanced.test.ts +165 -0
- package/typescript-tests/authority.test.ts +216 -0
- package/typescript-tests/expression.test.ts +228 -0
- package/typescript-tests/golden-payment-flow.test.ts +51 -0
- package/typescript-tests/graph.test.ts +142 -0
- package/typescript-tests/native-binding.test.ts +20 -0
- package/typescript-tests/primitives.test.ts +88 -0
- package/typescript-tests/registry.test.ts +122 -0
- package/typescript-tests/role_relation.test.ts +63 -0
- package/typescript-tests/runtime_toggle.test.ts +141 -0
- package/typescript-tests/semantic-pack.test.ts +556 -0
- package/typescript-tests/three_valued_eval.test.ts +135 -0
- package/typescript-tests/units.test.ts +36 -0
- package/vitest.config.ts +13 -0
- package/wasm_demo.html +225 -0
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
|
|
2
|
+
# SEA DSL ↔ CALM Mapping Specification
|
|
3
|
+
|
|
4
|
+
**Version:** 1.0
|
|
5
|
+
**Date:** 2025-11-07
|
|
6
|
+
**Status:** Implementation
|
|
7
|
+
**Aligned With:** ADR-006 (CALM), PRD-014 (CALM Interop), SDS-013 (CALM Serialization)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
FINOS CALM (Common Architecture Language Model) represents architecture as code using nodes and relationships. SEA DSL uses domain primitives with graph semantics. This document specifies the bidirectional mapping between these two representations.
|
|
14
|
+
|
|
15
|
+
## Mapping Strategy
|
|
16
|
+
|
|
17
|
+
### Core Principles
|
|
18
|
+
|
|
19
|
+
1. **Lossless Conversion**: All SEA DSL information must be preserved during export/import cycles
|
|
20
|
+
2. **CALM Compliance**: Exported JSON must validate against FINOS CALM v1.0 schema
|
|
21
|
+
3. **Metadata Preservation**: Domain-specific attributes stored in `metadata` field with `sea:` namespace prefix
|
|
22
|
+
4. **ID Mapping**: UUIDs converted to string format for CALM; remapping handled during import
|
|
23
|
+
|
|
24
|
+
### Mapping Table
|
|
25
|
+
|
|
26
|
+
| SEA Primitive | CALM Equivalent | Mapping Notes |
|
|
27
|
+
|---------------|-----------------|---------------|
|
|
28
|
+
| Entity | Node (type: actor/location) | Direct mapping; namespace preserved |
|
|
29
|
+
| Resource | Node (type: resource) | Unit stored in metadata |
|
|
30
|
+
| Flow | Relationship (type: flow) | Quantity attribute mapped to relationship metadata |
|
|
31
|
+
| Instance | Node (type: instance) + Relationship (ownership) | Composite mapping with parent entity link |
|
|
32
|
+
| Policy | Node (type: constraint) | SBVR expression stored in metadata |
|
|
33
|
+
| Entity Relationships | Relationship (type: association/aggregation) | Map association/aggregation links between entities |
|
|
34
|
+
| Instance-to-Entity Links | Relationship (type: ownership) | Map instance containment relationships |
|
|
35
|
+
| Inheritance | Node hierarchy + Relationship (type: inheritance) | Preserve type hierarchies as node relationships |
|
|
36
|
+
| Composition | Node composition + Relationship (type: composition) | Map composite object structures |
|
|
37
|
+
| Policy Propagation | Constraint propagation rules | Define how policies propagate across related nodes/flows |
|
|
38
|
+
| Domain Attributes | Node metadata | Preserve units, timestamps, provenance, ownership |
|
|
39
|
+
| Metadata Preservation | Node/relationship properties | Maintain domain-specific attributes during conversion |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Detailed Mappings
|
|
44
|
+
|
|
45
|
+
### 1. Entity → CALM Node
|
|
46
|
+
|
|
47
|
+
**SEA Entity Structure:**
|
|
48
|
+
```rust
|
|
49
|
+
Entity {
|
|
50
|
+
id: Uuid,
|
|
51
|
+
name: String,
|
|
52
|
+
namespace: String,
|
|
53
|
+
attributes: HashMap<String, Value>
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**CALM Node Structure:**
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"unique-id": "uuid-here",
|
|
61
|
+
"node-type": "actor",
|
|
62
|
+
"name": "Warehouse A",
|
|
63
|
+
"namespace": "logistics",
|
|
64
|
+
"metadata": {
|
|
65
|
+
"sea:primitive": "Entity",
|
|
66
|
+
"sea:attributes": {
|
|
67
|
+
"capacity": 10000,
|
|
68
|
+
"location": "Building 5"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Mapping Rules:**
|
|
75
|
+
- `Entity.id` → `unique-id` (converted to string)
|
|
76
|
+
- `Entity.name` → `name`
|
|
77
|
+
- `Entity.namespace` → `namespace`
|
|
78
|
+
- `Entity.attributes` → `metadata.sea:attributes`
|
|
79
|
+
- Add marker: `metadata.sea:primitive = "Entity"`
|
|
80
|
+
|
|
81
|
+
### 2. Resource → CALM Node
|
|
82
|
+
|
|
83
|
+
**SEA Resource Structure:**
|
|
84
|
+
```rust
|
|
85
|
+
Resource {
|
|
86
|
+
id: Uuid,
|
|
87
|
+
name: String,
|
|
88
|
+
unit: String,
|
|
89
|
+
attributes: HashMap<String, Value>
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**CALM Node Structure:**
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"unique-id": "resource-uuid",
|
|
97
|
+
"node-type": "resource",
|
|
98
|
+
"name": "Cameras",
|
|
99
|
+
"metadata": {
|
|
100
|
+
"sea:primitive": "Resource",
|
|
101
|
+
"sea:unit": "units",
|
|
102
|
+
"sea:attributes": {
|
|
103
|
+
"model": "HD-2000",
|
|
104
|
+
"cost_per_unit": 299.99
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Mapping Rules:**
|
|
111
|
+
- `Resource.id` → `unique-id`
|
|
112
|
+
- `Resource.name` → `name`
|
|
113
|
+
- `Resource.unit` → `metadata.sea:unit`
|
|
114
|
+
- `Resource.attributes` → `metadata.sea:attributes`
|
|
115
|
+
- `node-type` = `"resource"`
|
|
116
|
+
|
|
117
|
+
### 3. Flow → CALM Relationship
|
|
118
|
+
|
|
119
|
+
**SEA Flow Structure:**
|
|
120
|
+
```rust
|
|
121
|
+
Flow {
|
|
122
|
+
id: Uuid,
|
|
123
|
+
resource_id: Uuid,
|
|
124
|
+
from_entity_id: Uuid,
|
|
125
|
+
to_entity_id: Uuid,
|
|
126
|
+
quantity: i64
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**CALM Relationship Structure:**
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"unique-id": "flow-uuid",
|
|
134
|
+
"relationship-type": {
|
|
135
|
+
"flow": {
|
|
136
|
+
"resource": "resource-uuid",
|
|
137
|
+
"quantity": 100
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"parties": {
|
|
141
|
+
"source": "warehouse-uuid",
|
|
142
|
+
"destination": "factory-uuid"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Mapping Rules:**
|
|
148
|
+
- `Flow.id` → `unique-id`
|
|
149
|
+
- `Flow.resource_id` → `relationship-type.flow.resource`
|
|
150
|
+
- `Flow.quantity` → `relationship-type.flow.quantity`
|
|
151
|
+
- `Flow.from_entity_id` → `parties.source`
|
|
152
|
+
- `Flow.to_entity_id` → `parties.destination`
|
|
153
|
+
|
|
154
|
+
### 4. Instance → CALM Node + Relationship
|
|
155
|
+
|
|
156
|
+
**SEA Instance Structure:**
|
|
157
|
+
```rust
|
|
158
|
+
Instance {
|
|
159
|
+
id: Uuid,
|
|
160
|
+
resource_id: Uuid,
|
|
161
|
+
entity_id: Uuid,
|
|
162
|
+
attributes: HashMap<String, Value>
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**CALM Node Structure:**
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"unique-id": "instance-uuid",
|
|
170
|
+
"node-type": "instance",
|
|
171
|
+
"name": "Warehouse A Instance",
|
|
172
|
+
"metadata": {
|
|
173
|
+
"sea:primitive": "Instance",
|
|
174
|
+
"sea:entity_id": "entity-uuid",
|
|
175
|
+
"sea:attributes": {
|
|
176
|
+
"timestamp": "2025-11-07T12:00:00Z",
|
|
177
|
+
"status": "active"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**CALM Ownership Relationship:**
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"unique-id": "ownership-uuid",
|
|
187
|
+
"relationship-type": "ownership",
|
|
188
|
+
"parties": {
|
|
189
|
+
"owner": "entity-uuid",
|
|
190
|
+
"owned": "instance-uuid"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Mapping Rules:**
|
|
196
|
+
- `Instance.id` → `unique-id`
|
|
197
|
+
- `Instance.entity_id` → `metadata.sea:entity_id` AND `ownership relationship`
|
|
198
|
+
- `Instance.attributes` → `metadata.sea:attributes`
|
|
199
|
+
- Generate ownership relationship linking instance to parent entity
|
|
200
|
+
|
|
201
|
+
### Entity Relationships - Association → CALM Relationship
|
|
202
|
+
|
|
203
|
+
**CALM Relationship Structure (Association):**
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"unique-id": "assoc-1",
|
|
207
|
+
"relationship-type": "association",
|
|
208
|
+
"parties": {
|
|
209
|
+
"source": "entity-1",
|
|
210
|
+
"destination": "entity-2"
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Mapping Rules:**
|
|
216
|
+
- Associations are exported as `relationship-type: "association"` with `source` and `destination` set to the `unique-id` of the participating nodes.
|
|
217
|
+
- During import, associations are stored on the source entity as a metadata attribute `sea:associations` which contains an array of objects `{ "type": "association", "target": "<unique-id>" }` to preserve a lightweight representation that avoids adding extra primitives.
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
### 5. Policy → CALM Node
|
|
221
|
+
|
|
222
|
+
**SEA Policy Structure:**
|
|
223
|
+
```rust
|
|
224
|
+
Policy {
|
|
225
|
+
id: Uuid,
|
|
226
|
+
name: String,
|
|
227
|
+
expression: PolicyExpression
|
|
228
|
+
}
|
|
229
|
+
// Optional policy metadata fields exposed in mappings
|
|
230
|
+
modality: Option<String>, // e.g., "Obligation", "Permission"
|
|
231
|
+
kind: Option<String>, // e.g., enforcement kind or modality subtype
|
|
232
|
+
priority: Option<i32>, // integer priority for conflict resolution
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**CALM Node Structure:**
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"unique-id": "policy-uuid",
|
|
239
|
+
"node-type": "constraint",
|
|
240
|
+
"name": "Capacity Limit",
|
|
241
|
+
"metadata": {
|
|
242
|
+
"sea:primitive": "Policy",
|
|
243
|
+
"sea:expression": "ForAll entity: entity.capacity <= 10000",
|
|
244
|
+
"sea:expression_type": "SBVR"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Mapping Rules:**
|
|
250
|
+
- `Policy.id` → `unique-id`
|
|
251
|
+
- `Policy.name` → `name`
|
|
252
|
+
- `Policy.expression` → `metadata.sea:expression` (serialized as string)
|
|
253
|
+
- `node-type` = `"constraint"`
|
|
254
|
+
- `Policy.modality` → `metadata.sea:modality` (e.g., `Obligation`, `Prohibition`, `Permission`)
|
|
255
|
+
- `Policy.kind` → `metadata.sea:kind` (e.g., `Constraint`, `Derivation`, `Obligation`)
|
|
256
|
+
- `Policy.priority` → `metadata.sea:priority`
|
|
257
|
+
- `metadata.sea:expression_type` → `"SBVR"` or `"SEA"` - indicates whether expression uses SBVR or SEA DSL format
|
|
258
|
+
|
|
259
|
+
### PolicyExpression Serialization
|
|
260
|
+
|
|
261
|
+
The `PolicyExpression` enum serializes to SBVR (Semantics of Business Vocabulary and Rules) textual syntax for storage in `metadata.sea:expression`. Supported variants and their canonical SBVR syntax:
|
|
262
|
+
|
|
263
|
+
**Supported Variants:**
|
|
264
|
+
- `AtomicComparison(left, op, right)` → `"left op right"` (e.g., `"entity.capacity <= 10000"`)
|
|
265
|
+
- `QuantifierForAll(var, collection, condition)` → `"ForAll var in collection: condition"`
|
|
266
|
+
- `QuantifierExists(var, collection, condition)` → `"Exists var in collection: condition"`
|
|
267
|
+
- `LogicalAnd(left, right)` → `"left AND right"`
|
|
268
|
+
- `LogicalOr(left, right)` → `"left OR right"`
|
|
269
|
+
- `LogicalNot(expr)` → `"NOT expr"`
|
|
270
|
+
- `FunctionCall(name, args)` → `"name(args)"` (e.g., `"count(flows)"`)
|
|
271
|
+
|
|
272
|
+
**Serialization Rules:**
|
|
273
|
+
- **Variables**: Direct string representation (e.g., `"entity"`, `"flow"`)
|
|
274
|
+
- **Literals**: String representation of values (e.g., `"10000"`, `"Camera"`)
|
|
275
|
+
- **Operators**: Symbolic representation (`<=`, `>=`, `=`, `!=`, `<`, `>`)
|
|
276
|
+
- **Collections**: Lowercase plural names (`entities`, `resources`, `flows`, `instances`)
|
|
277
|
+
- **Escaping**: Double quotes around string literals containing spaces or special characters
|
|
278
|
+
- **Nesting**: Parentheses for complex expressions: `"(condition1) AND (condition2)"`
|
|
279
|
+
- **Enums/Identifiers**: Direct name mapping without quotes
|
|
280
|
+
|
|
281
|
+
**Example Mappings:**
|
|
282
|
+
- `QuantifierForAll("entity", "entities", AtomicComparison("entity.capacity", "<=", "10000"))` → `"ForAll entity in entities: entity.capacity <= 10000"`
|
|
283
|
+
- `LogicalAnd(AtomicComparison("flow.quantity", ">", "0"), AtomicComparison("flow.resource", "=", "Camera"))` → `"(flow.quantity > 0) AND (flow.resource = Camera)"`
|
|
284
|
+
|
|
285
|
+
**Deserialization (Parsing):**
|
|
286
|
+
- Parse SBVR syntax back to `PolicyExpression` enum variants
|
|
287
|
+
- Validate collection names against known types
|
|
288
|
+
- Handle operator precedence (AND/OR before comparisons)
|
|
289
|
+
- Error on unsupported constructs with descriptive messages
|
|
290
|
+
|
|
291
|
+
**Metadata:**
|
|
292
|
+
- `metadata.sea:expression_type`: `"SBVR"`
|
|
293
|
+
- `metadata.sea:expression_version`: `"1.0"` (for future compatibility)
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Import Strategy
|
|
298
|
+
|
|
299
|
+
### Node Import Algorithm
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
For each CALM node:
|
|
303
|
+
1. Read metadata.sea:primitive field
|
|
304
|
+
2. Switch on primitive type:
|
|
305
|
+
- "Entity" → Create Entity
|
|
306
|
+
- "Resource" → Create Resource
|
|
307
|
+
- "Instance" → Create Instance
|
|
308
|
+
- "Policy" → Create Policy
|
|
309
|
+
3. Map unique-id to internal UUID
|
|
310
|
+
4. Store in id_map for relationship resolution
|
|
311
|
+
5. Add to Graph
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Relationship Import Algorithm
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
For each CALM relationship:
|
|
318
|
+
1. Resolve source/destination IDs using id_map
|
|
319
|
+
2. Switch on relationship-type:
|
|
320
|
+
- "flow" → Create Flow
|
|
321
|
+
- "ownership" → Link Instance to Entity
|
|
322
|
+
- "association" → Create Entity association
|
|
323
|
+
- "composition" → Create composition link
|
|
324
|
+
3. Add to Graph
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### ID Remapping
|
|
328
|
+
|
|
329
|
+
During import, CALM `unique-id` values are mapped to new UUIDs:
|
|
330
|
+
|
|
331
|
+
```rust
|
|
332
|
+
let mut id_map: HashMap<String, Uuid> = HashMap::new();
|
|
333
|
+
|
|
334
|
+
for node in calm_nodes {
|
|
335
|
+
let calm_id = node["unique-id"].as_str();
|
|
336
|
+
let sea_id = Uuid::new_v4(); // Generate new UUID
|
|
337
|
+
id_map.insert(calm_id.to_string(), sea_id);
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Round-Trip Validation
|
|
344
|
+
|
|
345
|
+
### Semantic Equivalence
|
|
346
|
+
|
|
347
|
+
Since UUIDs are regenerated during import, equivalence is tested semantically:
|
|
348
|
+
|
|
349
|
+
1. **Entity Matching**: Match by `(name, namespace)` tuple
|
|
350
|
+
2. **Flow Matching**: Match by `(source_name, destination_name, resource_name, quantity)`
|
|
351
|
+
3. **Attribute Preservation**: All custom attributes must be preserved exactly
|
|
352
|
+
|
|
353
|
+
### Validation Tests
|
|
354
|
+
|
|
355
|
+
```rust
|
|
356
|
+
#[test]
|
|
357
|
+
fn test_lossless_round_trip() {
|
|
358
|
+
let graph1 = build_test_graph();
|
|
359
|
+
|
|
360
|
+
// Export to CALM
|
|
361
|
+
let calm_json = calm::export(&graph1)?;
|
|
362
|
+
|
|
363
|
+
// Import back
|
|
364
|
+
let graph2 = calm::import(calm_json)?;
|
|
365
|
+
|
|
366
|
+
// Verify semantic equivalence
|
|
367
|
+
assert_semantically_equivalent(&graph1, &graph2);
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Semantic Equivalence Definition
|
|
372
|
+
|
|
373
|
+
The `assert_semantically_equivalent` function compares two graphs for semantic equality, accounting for UUID regeneration during import:
|
|
374
|
+
|
|
375
|
+
- **Entities**: Match by `(name, namespace)` with identical attribute sets (keys equal, ordering ignored). Attribute values compared by deep equality with specific numeric rules: primitive ints/strings exact match, floats compared with epsilon (1e-9), NaN/inf handled explicitly, collections compared element-wise (preserve ordering unless domain says otherwise), maps compared by key/value deep-equality. Custom complex types must be canonicalized (sorted keys) before comparison.
|
|
376
|
+
- **Resources**: Match by `(name, unit)` with identical attribute sets using same comparison rules.
|
|
377
|
+
- **Flows**: Match by `(from_id, to_id, resource_id, quantity)` with quantity compared using numeric rules above. When name-based matching is used, the implementation may resolve names to IDs before asserting equivalence.
|
|
378
|
+
- **Instances**: Match by `(resource_id, entity_id, id)`; if the instance `id` is regenerated during import, matching may fall back to comparing `(resource_id, entity_id, attributes)`.
|
|
379
|
+
- **Policies**: Match by expression text and severity level.
|
|
380
|
+
|
|
381
|
+
```rust
|
|
382
|
+
fn assert_semantically_equivalent(graph1: &Graph, graph2: &Graph) {
|
|
383
|
+
// Implementation compares entities, resources, flows, instances, and policies
|
|
384
|
+
// using the rules above, failing the test if any mismatch is found
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## CALM Schema Compliance
|
|
391
|
+
|
|
392
|
+
All exports must validate against the FINOS CALM v1.0 JSON Schema:
|
|
393
|
+
|
|
394
|
+
- **Schema Source**: <https://github.com/finos/architecture-as-code>
|
|
395
|
+
- **Validation Tool**: `jsonschema` crate
|
|
396
|
+
- **Version**: CALM v1.0 (pinned)
|
|
397
|
+
|
|
398
|
+
### Required CALM Fields
|
|
399
|
+
|
|
400
|
+
- `nodes`: Array of node objects
|
|
401
|
+
- `relationships`: Array of relationship objects
|
|
402
|
+
- `version`: String (e.g., "1.0")
|
|
403
|
+
- `metadata`: Object with export metadata
|
|
404
|
+
|
|
405
|
+
### CALM Node Required Fields
|
|
406
|
+
|
|
407
|
+
- `unique-id`: String
|
|
408
|
+
- `node-type`: String (actor/location/resource/instance/constraint)
|
|
409
|
+
- `name`: String
|
|
410
|
+
- `metadata`: Object (optional but used for SEA attributes)
|
|
411
|
+
|
|
412
|
+
### CALM Relationship Required Fields
|
|
413
|
+
|
|
414
|
+
- `unique-id`: String
|
|
415
|
+
- `relationship-type`: String or Object
|
|
416
|
+
- `parties`: Object with source/destination or owner/owned
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Export Format Example
|
|
421
|
+
|
|
422
|
+
```json
|
|
423
|
+
{
|
|
424
|
+
"version": "1.0",
|
|
425
|
+
"metadata": {
|
|
426
|
+
"sea:exported": true,
|
|
427
|
+
"sea:version": "0.1.0",
|
|
428
|
+
"sea:timestamp": "2025-11-07T12:00:00Z"
|
|
429
|
+
},
|
|
430
|
+
"nodes": [
|
|
431
|
+
{
|
|
432
|
+
"unique-id": "entity-1",
|
|
433
|
+
"node-type": "actor",
|
|
434
|
+
"name": "Warehouse",
|
|
435
|
+
"namespace": "logistics",
|
|
436
|
+
"metadata": {
|
|
437
|
+
"sea:primitive": "Entity",
|
|
438
|
+
"sea:attributes": {
|
|
439
|
+
"capacity": 10000
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"unique-id": "resource-1",
|
|
445
|
+
"node-type": "resource",
|
|
446
|
+
"name": "Cameras",
|
|
447
|
+
"metadata": {
|
|
448
|
+
"sea:primitive": "Resource",
|
|
449
|
+
"sea:unit": "units"
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
],
|
|
453
|
+
"relationships": [
|
|
454
|
+
{
|
|
455
|
+
"unique-id": "flow-1",
|
|
456
|
+
"relationship-type": {
|
|
457
|
+
"flow": {
|
|
458
|
+
"resource": "resource-1",
|
|
459
|
+
"quantity": 100
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
"parties": {
|
|
463
|
+
"source": "entity-1",
|
|
464
|
+
"destination": "entity-2"
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## Error Handling
|
|
474
|
+
|
|
475
|
+
### Export Errors
|
|
476
|
+
|
|
477
|
+
- **Missing Required Field**: If Entity missing name/namespace → Return error
|
|
478
|
+
- **Invalid UUID**: Should never occur (internal consistency)
|
|
479
|
+
- **Serialization Failure**: If attributes contain non-JSON types → Return error
|
|
480
|
+
|
|
481
|
+
### Import Errors
|
|
482
|
+
|
|
483
|
+
- **Invalid JSON**: Parse error → Return detailed error message
|
|
484
|
+
- **Missing Required Field**: Missing `unique-id` → Skip node and log warning
|
|
485
|
+
- **Unresolved ID Reference**: Relationship references unknown node → Return error
|
|
486
|
+
- **Unknown Node Type**: Unrecognized `node-type` → Skip and log warning
|
|
487
|
+
- **Schema Validation Failure**: Does not match CALM schema → Return validation errors
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## Future Extensions
|
|
492
|
+
|
|
493
|
+
1. **Provenance Tracking**: Add import/export history to metadata
|
|
494
|
+
2. **Versioning**: Support CALM schema version detection and migration
|
|
495
|
+
3. **Custom Node Types**: Allow user-defined node types beyond CALM spec
|
|
496
|
+
4. **Diff/Merge**: Support for comparing CALM models and merging changes
|
|
497
|
+
5. **Streaming**: Large model export/import with streaming JSON parser
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## References
|
|
502
|
+
|
|
503
|
+
- [FINOS CALM Specification](https://github.com/finos/architecture-as-code)
|
|
504
|
+
- ADR-006: CALM Integration Architecture Decision
|
|
505
|
+
- PRD-014: CALM Interoperability Requirements
|
|
506
|
+
- SDS-013: CALM Serialization System Design
|
|
507
|
+
|
|
508
|
+
## Implementation pointers
|
|
509
|
+
|
|
510
|
+
- Export logic: `domainforge-core/src/calm/export.rs`
|
|
511
|
+
- Import logic: `domainforge-core/src/calm/import.rs`
|
|
512
|
+
- Round-trip tests: `domainforge-core/tests/calm_round_trip_tests.rs`
|
|
513
|
+
|
|
514
|
+
Bindings expose these projections via `Graph.export_calm()` (Python) and `graph.exportCalm()` (TypeScript). Validation codes mirror those in `error-codes.md` when CALM payloads lack required fields.
|
|
515
|
+
|
|
516
|
+
## See also
|
|
517
|
+
|
|
518
|
+
- `docs/new_docs/how-tos/export-to-calm.md` for end-to-end export steps.
|
|
519
|
+
- `docs/new_docs/how-tos/import-from-calm.md` for import and round-trip validation.
|