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,367 @@
|
|
|
1
|
+
# SDS-006: CALM Integration
|
|
2
|
+
|
|
3
|
+
**System:** DomainForge
|
|
4
|
+
**Component:** FINOS CALM Import/Export
|
|
5
|
+
**Version:** 1.0
|
|
6
|
+
**Date:** 2025-12-14
|
|
7
|
+
**Status:** Implemented
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Overview
|
|
12
|
+
|
|
13
|
+
The CALM (Common Architecture Language Model) integration enables DomainForge to:
|
|
14
|
+
|
|
15
|
+
- Export SEA models to FINOS CALM JSON format
|
|
16
|
+
- Import FINOS CALM architecture models into SEA
|
|
17
|
+
- Support enterprise architecture governance workflows
|
|
18
|
+
- Enable architecture-as-code practices
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. FINOS CALM Background
|
|
23
|
+
|
|
24
|
+
CALM is a standardized format for describing enterprise architectures:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"$schema": "https://calm.finos.org/draft/2024-03/meta/core.json",
|
|
29
|
+
"nodes": [...],
|
|
30
|
+
"relationships": [...]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Key CALM concepts:
|
|
35
|
+
|
|
36
|
+
- **Nodes**: Architectural components (services, systems, actors)
|
|
37
|
+
- **Relationships**: Connections between nodes
|
|
38
|
+
- **Interfaces**: API contracts and interactions
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 3. Architecture
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
┌────────────────────────────────────────────────────┐
|
|
46
|
+
│ calm/ Module │
|
|
47
|
+
├────────────────────────────────────────────────────┤
|
|
48
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
49
|
+
│ │ CalmModel │ │ CalmNode │ │
|
|
50
|
+
│ └──────────────┘ └──────────────┘ │
|
|
51
|
+
│ ┌──────────────────────────────────┐ │
|
|
52
|
+
│ │ CalmRelationship │ │
|
|
53
|
+
│ └──────────────────────────────────┘ │
|
|
54
|
+
├────────────────────────────────────────────────────┤
|
|
55
|
+
│ export.rs │ import.rs │
|
|
56
|
+
│ - export() │ - import() │
|
|
57
|
+
│ - graph_to_calm() │ - calm_to_graph() │
|
|
58
|
+
├────────────────────────────────────────────────────┤
|
|
59
|
+
│ sbvr_import.rs │
|
|
60
|
+
│ - import_sbvr_xmi() │
|
|
61
|
+
└────────────────────────────────────────────────────┘
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 4. Core Types
|
|
67
|
+
|
|
68
|
+
### 4.1 CalmModel
|
|
69
|
+
|
|
70
|
+
```rust
|
|
71
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
72
|
+
pub struct CalmModel {
|
|
73
|
+
#[serde(rename = "$schema")]
|
|
74
|
+
pub schema: String,
|
|
75
|
+
pub nodes: Vec<CalmNode>,
|
|
76
|
+
pub relationships: Vec<CalmRelationship>,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
impl CalmModel {
|
|
80
|
+
pub fn new() -> Self {
|
|
81
|
+
Self {
|
|
82
|
+
schema: "https://calm.finos.org/draft/2024-03/meta/core.json".to_string(),
|
|
83
|
+
nodes: Vec::new(),
|
|
84
|
+
relationships: Vec::new(),
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4.2 CalmNode
|
|
91
|
+
|
|
92
|
+
```rust
|
|
93
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
94
|
+
pub struct CalmNode {
|
|
95
|
+
#[serde(rename = "unique-id")]
|
|
96
|
+
pub unique_id: String,
|
|
97
|
+
|
|
98
|
+
pub name: String,
|
|
99
|
+
|
|
100
|
+
#[serde(rename = "node-type")]
|
|
101
|
+
pub node_type: String,
|
|
102
|
+
|
|
103
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
104
|
+
pub description: Option<String>,
|
|
105
|
+
|
|
106
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
107
|
+
pub interfaces: Option<Vec<CalmInterface>>,
|
|
108
|
+
|
|
109
|
+
#[serde(flatten)]
|
|
110
|
+
pub extra: HashMap<String, serde_json::Value>,
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 4.3 CalmRelationship
|
|
115
|
+
|
|
116
|
+
```rust
|
|
117
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
118
|
+
pub struct CalmRelationship {
|
|
119
|
+
#[serde(rename = "unique-id")]
|
|
120
|
+
pub unique_id: String,
|
|
121
|
+
|
|
122
|
+
#[serde(rename = "relationship-type")]
|
|
123
|
+
pub relationship_type: RelationshipType,
|
|
124
|
+
|
|
125
|
+
pub parties: Parties,
|
|
126
|
+
|
|
127
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
128
|
+
pub description: Option<String>,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
132
|
+
pub struct Parties {
|
|
133
|
+
pub source: String,
|
|
134
|
+
pub destination: String,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
138
|
+
#[serde(rename_all = "lowercase")]
|
|
139
|
+
pub enum RelationshipType {
|
|
140
|
+
Connects,
|
|
141
|
+
Interacts,
|
|
142
|
+
Deployed,
|
|
143
|
+
Composed,
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 5. Mapping Rules
|
|
150
|
+
|
|
151
|
+
### 5.1 SEA → CALM Mappings
|
|
152
|
+
|
|
153
|
+
| SEA Concept | CALM Mapping |
|
|
154
|
+
| ----------- | ------------------------------------------------------- |
|
|
155
|
+
| Entity | `CalmNode` with `node-type: "system"` or `"actor"` |
|
|
156
|
+
| Resource | `CalmNode` with `node-type: "data-asset"` |
|
|
157
|
+
| Flow | `CalmRelationship` with `relationship-type: "connects"` |
|
|
158
|
+
| Role | `CalmNode` with `node-type: "actor"` |
|
|
159
|
+
| Relation | `CalmRelationship` with appropriate type |
|
|
160
|
+
|
|
161
|
+
### 5.2 Node Type Inference
|
|
162
|
+
|
|
163
|
+
```rust
|
|
164
|
+
fn infer_node_type(entity: &Entity) -> String {
|
|
165
|
+
// Use entity attributes or naming conventions
|
|
166
|
+
if entity.name().ends_with("Service") {
|
|
167
|
+
"service".to_string()
|
|
168
|
+
} else if entity.name().ends_with("Database") || entity.name().ends_with("Store") {
|
|
169
|
+
"database".to_string()
|
|
170
|
+
} else if entity.has_role("Actor") {
|
|
171
|
+
"actor".to_string()
|
|
172
|
+
} else {
|
|
173
|
+
"system".to_string()
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 6. Export Process
|
|
181
|
+
|
|
182
|
+
### 6.1 Graph to CALM
|
|
183
|
+
|
|
184
|
+
```rust
|
|
185
|
+
pub fn export(graph: &Graph) -> Result<CalmModel, CalmError> {
|
|
186
|
+
let mut model = CalmModel::new();
|
|
187
|
+
|
|
188
|
+
// Export entities as nodes
|
|
189
|
+
for entity in graph.all_entities() {
|
|
190
|
+
model.nodes.push(CalmNode {
|
|
191
|
+
unique_id: entity.id().to_string(),
|
|
192
|
+
name: entity.name().to_string(),
|
|
193
|
+
node_type: infer_node_type(entity),
|
|
194
|
+
description: entity.get_attribute("description")
|
|
195
|
+
.and_then(|v| v.as_str().map(String::from)),
|
|
196
|
+
interfaces: None,
|
|
197
|
+
extra: HashMap::new(),
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Export resources as data assets
|
|
202
|
+
for resource in graph.all_resources() {
|
|
203
|
+
model.nodes.push(CalmNode {
|
|
204
|
+
unique_id: resource.id().to_string(),
|
|
205
|
+
name: resource.name().to_string(),
|
|
206
|
+
node_type: "data-asset".to_string(),
|
|
207
|
+
description: None,
|
|
208
|
+
interfaces: None,
|
|
209
|
+
extra: HashMap::new(),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Export flows as relationships
|
|
214
|
+
for flow in graph.all_flows() {
|
|
215
|
+
model.relationships.push(CalmRelationship {
|
|
216
|
+
unique_id: flow.id().to_string(),
|
|
217
|
+
relationship_type: RelationshipType::Connects,
|
|
218
|
+
parties: Parties {
|
|
219
|
+
source: flow.from_id().to_string(),
|
|
220
|
+
destination: flow.to_id().to_string(),
|
|
221
|
+
},
|
|
222
|
+
description: Some(format!(
|
|
223
|
+
"{} (quantity: {})",
|
|
224
|
+
graph.get_resource(flow.resource_id())
|
|
225
|
+
.map(|r| r.name())
|
|
226
|
+
.unwrap_or("unknown"),
|
|
227
|
+
flow.quantity()
|
|
228
|
+
)),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
Ok(model)
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 6.2 JSON Serialization
|
|
237
|
+
|
|
238
|
+
```rust
|
|
239
|
+
impl CalmModel {
|
|
240
|
+
pub fn to_json(&self) -> Result<String, CalmError> {
|
|
241
|
+
serde_json::to_string_pretty(self)
|
|
242
|
+
.map_err(|e| CalmError::Serialization(e.to_string()))
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
pub fn to_json_compact(&self) -> Result<String, CalmError> {
|
|
246
|
+
serde_json::to_string(self)
|
|
247
|
+
.map_err(|e| CalmError::Serialization(e.to_string()))
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 7. Import Process
|
|
255
|
+
|
|
256
|
+
### 7.1 CALM to Graph
|
|
257
|
+
|
|
258
|
+
```rust
|
|
259
|
+
pub fn import(json: &str) -> Result<Graph, CalmError> {
|
|
260
|
+
let model: CalmModel = serde_json::from_str(json)
|
|
261
|
+
.map_err(|e| CalmError::Parse(e.to_string()))?;
|
|
262
|
+
|
|
263
|
+
let mut graph = Graph::new();
|
|
264
|
+
|
|
265
|
+
// Import nodes
|
|
266
|
+
for node in model.nodes {
|
|
267
|
+
match node.node_type.as_str() {
|
|
268
|
+
"actor" | "system" | "service" => {
|
|
269
|
+
let entity = Entity::new_with_namespace(
|
|
270
|
+
node.name.clone(),
|
|
271
|
+
"calm".to_string(),
|
|
272
|
+
);
|
|
273
|
+
graph.add_entity(entity)?;
|
|
274
|
+
}
|
|
275
|
+
"data-asset" => {
|
|
276
|
+
let resource = Resource::new_with_namespace(
|
|
277
|
+
node.name.clone(),
|
|
278
|
+
Unit::count(),
|
|
279
|
+
"calm".to_string(),
|
|
280
|
+
);
|
|
281
|
+
graph.add_resource(resource)?;
|
|
282
|
+
}
|
|
283
|
+
_ => {
|
|
284
|
+
// Unknown node types become entities
|
|
285
|
+
let entity = Entity::new_with_namespace(
|
|
286
|
+
node.name.clone(),
|
|
287
|
+
"calm".to_string(),
|
|
288
|
+
);
|
|
289
|
+
graph.add_entity(entity)?;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Import relationships as flows (where applicable)
|
|
295
|
+
for rel in model.relationships {
|
|
296
|
+
if rel.relationship_type == RelationshipType::Connects {
|
|
297
|
+
// Create a synthetic resource for the flow
|
|
298
|
+
let resource_name = format!("{}→{}", rel.parties.source, rel.parties.destination);
|
|
299
|
+
// ...
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
Ok(graph)
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## 8. CLI Integration
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# Export to CALM
|
|
313
|
+
domainforge project --format calm model.sea > architecture.json
|
|
314
|
+
|
|
315
|
+
# Import from CALM
|
|
316
|
+
domainforge import --from calm architecture.json > model.sea
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 9. Validation
|
|
322
|
+
|
|
323
|
+
### 9.1 CALM Schema Validation
|
|
324
|
+
|
|
325
|
+
```rust
|
|
326
|
+
pub fn validate_calm_schema(json: &str) -> Result<(), CalmError> {
|
|
327
|
+
let model: CalmModel = serde_json::from_str(json)?;
|
|
328
|
+
|
|
329
|
+
// Check required fields
|
|
330
|
+
for node in &model.nodes {
|
|
331
|
+
if node.unique_id.is_empty() {
|
|
332
|
+
return Err(CalmError::Validation("Node missing unique-id".to_string()));
|
|
333
|
+
}
|
|
334
|
+
if node.name.is_empty() {
|
|
335
|
+
return Err(CalmError::Validation("Node missing name".to_string()));
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Check relationship references
|
|
340
|
+
let node_ids: HashSet<_> = model.nodes.iter()
|
|
341
|
+
.map(|n| n.unique_id.as_str())
|
|
342
|
+
.collect();
|
|
343
|
+
|
|
344
|
+
for rel in &model.relationships {
|
|
345
|
+
if !node_ids.contains(rel.parties.source.as_str()) {
|
|
346
|
+
return Err(CalmError::Validation(
|
|
347
|
+
format!("Relationship references unknown source: {}", rel.parties.source)
|
|
348
|
+
));
|
|
349
|
+
}
|
|
350
|
+
if !node_ids.contains(rel.parties.destination.as_str()) {
|
|
351
|
+
return Err(CalmError::Validation(
|
|
352
|
+
format!("Relationship references unknown destination: {}", rel.parties.destination)
|
|
353
|
+
));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
Ok(())
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Related Documents
|
|
364
|
+
|
|
365
|
+
- [ADR-001: SEA-DSL as Semantic Source of Truth](./ADR-001-sea-dsl-semantic-source-of-truth.md)
|
|
366
|
+
- [SDS-002: SEA Core Architecture](./SDS-002-domainforge-core-architecture.md)
|
|
367
|
+
- [PRD-002: SEA CLI Tooling](./PRD-002-sea-cli-tooling.md)
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# SDS-007: SBVR Import
|
|
2
|
+
|
|
3
|
+
**System:** DomainForge
|
|
4
|
+
**Component:** SBVR XMI Import
|
|
5
|
+
**Version:** 1.0
|
|
6
|
+
**Date:** 2025-12-14
|
|
7
|
+
**Status:** Implemented
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Overview
|
|
12
|
+
|
|
13
|
+
The SBVR (Semantics of Business Vocabulary and Rules) import module enables DomainForge to:
|
|
14
|
+
|
|
15
|
+
- Import OMG SBVR XMI files into SEA graphs
|
|
16
|
+
- Convert SBVR fact types to SEA relations
|
|
17
|
+
- Transform SBVR rules to SEA policies
|
|
18
|
+
- Preserve business vocabulary semantics
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. SBVR Background
|
|
23
|
+
|
|
24
|
+
SBVR is an OMG standard for expressing business vocabularies and rules in natural language with formal semantics. Key concepts:
|
|
25
|
+
|
|
26
|
+
- **Noun Concepts**: Business terms (e.g., "Customer", "Order")
|
|
27
|
+
- **Verb Concepts**: Relationships between terms (e.g., "places", "contains")
|
|
28
|
+
- **Fact Types**: Structured propositions (e.g., "Customer places Order")
|
|
29
|
+
- **Business Rules**: Constraints and derivation rules
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 3. Architecture
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
┌────────────────────────────────────────────────────┐
|
|
37
|
+
│ sbvr.rs Module │
|
|
38
|
+
├────────────────────────────────────────────────────┤
|
|
39
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
40
|
+
│ │ SbvrModel │ │ NounConcept │ │
|
|
41
|
+
│ └──────────────┘ └──────────────┘ │
|
|
42
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
43
|
+
│ │ VerbConcept │ │ FactType │ │
|
|
44
|
+
│ └──────────────┘ └──────────────┘ │
|
|
45
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
46
|
+
│ │BusinessRule │ │ Definition │ │
|
|
47
|
+
│ └──────────────┘ └──────────────┘ │
|
|
48
|
+
├────────────────────────────────────────────────────┤
|
|
49
|
+
│ Parsing Methods │
|
|
50
|
+
│ - from_xmi() │
|
|
51
|
+
│ - to_graph() │
|
|
52
|
+
└────────────────────────────────────────────────────┘
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. Core Types
|
|
58
|
+
|
|
59
|
+
### 4.1 SbvrModel
|
|
60
|
+
|
|
61
|
+
```rust
|
|
62
|
+
pub struct SbvrModel {
|
|
63
|
+
pub name: String,
|
|
64
|
+
pub noun_concepts: Vec<NounConcept>,
|
|
65
|
+
pub verb_concepts: Vec<VerbConcept>,
|
|
66
|
+
pub fact_types: Vec<FactType>,
|
|
67
|
+
pub business_rules: Vec<BusinessRule>,
|
|
68
|
+
pub definitions: Vec<Definition>,
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 4.2 NounConcept
|
|
73
|
+
|
|
74
|
+
```rust
|
|
75
|
+
pub struct NounConcept {
|
|
76
|
+
pub id: String,
|
|
77
|
+
pub name: String,
|
|
78
|
+
pub definition: Option<String>,
|
|
79
|
+
pub synonyms: Vec<String>,
|
|
80
|
+
pub general_concept: Option<String>, // Parent concept
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 4.3 VerbConcept
|
|
85
|
+
|
|
86
|
+
```rust
|
|
87
|
+
pub struct VerbConcept {
|
|
88
|
+
pub id: String,
|
|
89
|
+
pub name: String, // e.g., "places"
|
|
90
|
+
pub roles: Vec<Role>, // Subject and object roles
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
pub struct Role {
|
|
94
|
+
pub name: String,
|
|
95
|
+
pub noun_concept_id: String,
|
|
96
|
+
pub cardinality: Cardinality,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
pub enum Cardinality {
|
|
100
|
+
One,
|
|
101
|
+
ZeroOrOne,
|
|
102
|
+
OneOrMore,
|
|
103
|
+
ZeroOrMore,
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 4.4 FactType
|
|
108
|
+
|
|
109
|
+
```rust
|
|
110
|
+
pub struct FactType {
|
|
111
|
+
pub id: String,
|
|
112
|
+
pub reading: String, // e.g., "Customer places Order"
|
|
113
|
+
pub verb_concept_id: String,
|
|
114
|
+
pub role_bindings: Vec<(String, String)>, // (role_id, concept_id)
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 4.5 BusinessRule
|
|
119
|
+
|
|
120
|
+
```rust
|
|
121
|
+
pub struct BusinessRule {
|
|
122
|
+
pub id: String,
|
|
123
|
+
pub name: String,
|
|
124
|
+
pub statement: String, // Natural language
|
|
125
|
+
pub rule_type: RuleType,
|
|
126
|
+
pub fact_type_refs: Vec<String>,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
pub enum RuleType {
|
|
130
|
+
StructuralRule, // Cardinality, uniqueness
|
|
131
|
+
DerivationRule, // Computed facts
|
|
132
|
+
OperativeRule, // Business constraints
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 5. XMI Parsing
|
|
139
|
+
|
|
140
|
+
### 5.1 Parser Implementation
|
|
141
|
+
|
|
142
|
+
```rust
|
|
143
|
+
impl SbvrModel {
|
|
144
|
+
pub fn from_xmi(xmi: &str) -> Result<Self, SbvrError> {
|
|
145
|
+
let doc = roxmltree::Document::parse(xmi)
|
|
146
|
+
.map_err(|e| SbvrError::Parse(e.to_string()))?;
|
|
147
|
+
|
|
148
|
+
let mut model = SbvrModel::default();
|
|
149
|
+
|
|
150
|
+
// Parse noun concepts
|
|
151
|
+
for node in doc.descendants().filter(|n| n.has_tag_name("nounConcept")) {
|
|
152
|
+
model.noun_concepts.push(NounConcept {
|
|
153
|
+
id: node.attribute("xmi:id").unwrap_or_default().to_string(),
|
|
154
|
+
name: node.attribute("name").unwrap_or_default().to_string(),
|
|
155
|
+
definition: node.children()
|
|
156
|
+
.find(|n| n.has_tag_name("definition"))
|
|
157
|
+
.and_then(|n| n.text().map(String::from)),
|
|
158
|
+
synonyms: Vec::new(),
|
|
159
|
+
general_concept: node.attribute("generalConcept").map(String::from),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Parse verb concepts
|
|
164
|
+
for node in doc.descendants().filter(|n| n.has_tag_name("verbConcept")) {
|
|
165
|
+
// ...
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Parse fact types
|
|
169
|
+
for node in doc.descendants().filter(|n| n.has_tag_name("factType")) {
|
|
170
|
+
// ...
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Parse business rules
|
|
174
|
+
for node in doc.descendants().filter(|n| n.has_tag_name("businessRule")) {
|
|
175
|
+
// ...
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
Ok(model)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 6. Conversion to SEA Graph
|
|
186
|
+
|
|
187
|
+
### 6.1 Mapping Strategy
|
|
188
|
+
|
|
189
|
+
| SBVR Concept | SEA Mapping |
|
|
190
|
+
| -------------------------- | ---------------------------- |
|
|
191
|
+
| Noun Concept | Entity |
|
|
192
|
+
| Verb Concept | Relation (predicate) |
|
|
193
|
+
| Fact Type | Role-based Relation |
|
|
194
|
+
| Business Rule (structural) | Policy |
|
|
195
|
+
| Business Rule (operative) | Policy |
|
|
196
|
+
| Definition | Entity description attribute |
|
|
197
|
+
|
|
198
|
+
### 6.2 Conversion Implementation
|
|
199
|
+
|
|
200
|
+
```rust
|
|
201
|
+
impl SbvrModel {
|
|
202
|
+
pub fn to_graph(&self) -> Result<Graph, SbvrError> {
|
|
203
|
+
let mut graph = Graph::new();
|
|
204
|
+
|
|
205
|
+
// Convert noun concepts to entities
|
|
206
|
+
for noun in &self.noun_concepts {
|
|
207
|
+
let mut entity = Entity::new_with_namespace(
|
|
208
|
+
noun.name.clone(),
|
|
209
|
+
"sbvr".to_string(),
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
if let Some(def) = &noun.definition {
|
|
213
|
+
entity.set_attribute("description", serde_json::json!(def));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
graph.add_entity(entity)?;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Convert verb concepts to roles
|
|
220
|
+
for verb in &self.verb_concepts {
|
|
221
|
+
for role in &verb.roles {
|
|
222
|
+
let sea_role = Role::new_with_namespace(
|
|
223
|
+
role.name.clone(),
|
|
224
|
+
"sbvr".to_string(),
|
|
225
|
+
);
|
|
226
|
+
graph.add_role(sea_role)?;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Convert fact types to relations
|
|
231
|
+
for fact in &self.fact_types {
|
|
232
|
+
if let Some(verb) = self.verb_concepts.iter().find(|v| v.id == fact.verb_concept_id) {
|
|
233
|
+
if verb.roles.len() >= 2 {
|
|
234
|
+
let subject_role_id = graph.find_role_by_name(&verb.roles[0].name)
|
|
235
|
+
.ok_or(SbvrError::Conversion("Role not found".to_string()))?;
|
|
236
|
+
let object_role_id = graph.find_role_by_name(&verb.roles[1].name)
|
|
237
|
+
.ok_or(SbvrError::Conversion("Role not found".to_string()))?;
|
|
238
|
+
|
|
239
|
+
let relation = RelationType::new(
|
|
240
|
+
verb.name.clone(),
|
|
241
|
+
subject_role_id,
|
|
242
|
+
object_role_id,
|
|
243
|
+
verb.name.clone(), // predicate
|
|
244
|
+
);
|
|
245
|
+
graph.add_relation_type(relation)?;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Convert business rules to policies
|
|
251
|
+
for rule in &self.business_rules {
|
|
252
|
+
let policy = self.convert_rule_to_policy(rule)?;
|
|
253
|
+
graph.add_policy(policy)?;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
Ok(graph)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
fn convert_rule_to_policy(&self, rule: &BusinessRule) -> Result<Policy, SbvrError> {
|
|
260
|
+
// Convert SBVR statement to SEA expression
|
|
261
|
+
// This is a simplified mapping; full SBVR requires more complex parsing
|
|
262
|
+
let expression = self.parse_sbvr_statement(&rule.statement)?;
|
|
263
|
+
|
|
264
|
+
Ok(Policy {
|
|
265
|
+
id: ConceptId::new("sbvr", &rule.name),
|
|
266
|
+
name: rule.name.clone(),
|
|
267
|
+
expression,
|
|
268
|
+
severity: match rule.rule_type {
|
|
269
|
+
RuleType::StructuralRule => Severity::Error,
|
|
270
|
+
RuleType::OperativeRule => Severity::Warning,
|
|
271
|
+
RuleType::DerivationRule => Severity::Info,
|
|
272
|
+
},
|
|
273
|
+
description: Some(rule.statement.clone()),
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## 7. SBVR Statement Parsing
|
|
282
|
+
|
|
283
|
+
### 7.1 Supported Patterns
|
|
284
|
+
|
|
285
|
+
| SBVR Pattern | SEA Expression |
|
|
286
|
+
| -------------------------- | -------------------------- |
|
|
287
|
+
| "Each X must Y" | `forall x in X: Y(x)` |
|
|
288
|
+
| "At most one X per Y" | Cardinality check |
|
|
289
|
+
| "It is necessary that..." | Policy with error severity |
|
|
290
|
+
| "It is permitted that..." | No policy (allowed) |
|
|
291
|
+
| "It is obligatory that..." | Policy with error severity |
|
|
292
|
+
|
|
293
|
+
### 7.2 Expression Conversion
|
|
294
|
+
|
|
295
|
+
```rust
|
|
296
|
+
fn parse_sbvr_statement(&self, statement: &str) -> Result<Expression, SbvrError> {
|
|
297
|
+
let normalized = statement.to_lowercase();
|
|
298
|
+
|
|
299
|
+
// Pattern: "Each X must have at least one Y"
|
|
300
|
+
if normalized.contains("each") && normalized.contains("must have") {
|
|
301
|
+
// Extract subject and object
|
|
302
|
+
// Build forall expression
|
|
303
|
+
// ...
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Pattern: "It is necessary that..."
|
|
307
|
+
if normalized.starts_with("it is necessary that") {
|
|
308
|
+
// Extract constraint
|
|
309
|
+
// Build expression
|
|
310
|
+
// ...
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Default: store as raw statement for manual review
|
|
314
|
+
Ok(Expression::Literal(Value::String(statement.to_string())))
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## 8. CLI Integration
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
# Import SBVR XMI file
|
|
324
|
+
domainforge import --from sbvr vocabulary.xmi > model.sea
|
|
325
|
+
|
|
326
|
+
# Import with namespace override
|
|
327
|
+
domainforge import --from sbvr --namespace my-domain vocabulary.xmi
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 9. Limitations
|
|
333
|
+
|
|
334
|
+
| Limitation | Workaround |
|
|
335
|
+
| -------------------- | --------------------------------- |
|
|
336
|
+
| Complex quantifiers | Manual policy authoring |
|
|
337
|
+
| Computed derivations | Not supported (logged as warning) |
|
|
338
|
+
| Temporal rules | Limited support via ConceptChange |
|
|
339
|
+
| Modal logic | Mapped to severity levels |
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Related Documents
|
|
344
|
+
|
|
345
|
+
- [ADR-001: SEA-DSL as Semantic Source of Truth](./ADR-001-sea-dsl-semantic-source-of-truth.md)
|
|
346
|
+
- [SDS-004: Policy Engine Design](./SDS-004-policy-engine-design.md)
|
|
347
|
+
- [PRD-003: DSL Core Capabilities](./PRD-003-dsl-core-capabilities.md)
|