@memoarchitect/tools 0.6.7 → 0.8.7
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/README.md +36 -11
- package/corpus/README.md +63 -0
- package/corpus/sysml-v2-release/bnf/SysML-graphical-bnf.kgbnf +2264 -0
- package/package.json +20 -7
- package/packages/tools/lib/analysis/dsm.d.ts +1 -1
- package/packages/tools/lib/analysis/dsm.d.ts.map +1 -1
- package/packages/tools/lib/analysis/dsm.js +1 -1
- package/packages/tools/lib/analysis/dsm.js.map +1 -1
- package/packages/tools/lib/bin/memo.js +186 -10
- package/packages/tools/lib/bin/memo.js.map +1 -1
- package/packages/tools/lib/browser/index.d.ts +3 -1
- package/packages/tools/lib/browser/index.d.ts.map +1 -1
- package/packages/tools/lib/browser/index.js +2 -1
- package/packages/tools/lib/browser/index.js.map +1 -1
- package/packages/tools/lib/commands/ask.js +1 -1
- package/packages/tools/lib/commands/ask.js.map +1 -1
- package/packages/tools/lib/commands/check.d.ts.map +1 -1
- package/packages/tools/lib/commands/check.js +3 -9
- package/packages/tools/lib/commands/check.js.map +1 -1
- package/packages/tools/lib/commands/conformance.d.ts +36 -0
- package/packages/tools/lib/commands/conformance.d.ts.map +1 -0
- package/packages/tools/lib/commands/conformance.js +212 -0
- package/packages/tools/lib/commands/conformance.js.map +1 -0
- package/packages/tools/lib/commands/convert.d.ts +12 -0
- package/packages/tools/lib/commands/convert.d.ts.map +1 -0
- package/packages/tools/lib/commands/convert.js +103 -0
- package/packages/tools/lib/commands/convert.js.map +1 -0
- package/packages/tools/lib/commands/create-package.d.ts +1 -2
- package/packages/tools/lib/commands/create-package.d.ts.map +1 -1
- package/packages/tools/lib/commands/create-package.js.map +1 -1
- package/packages/tools/lib/commands/dev.d.ts +13 -0
- package/packages/tools/lib/commands/dev.d.ts.map +1 -1
- package/packages/tools/lib/commands/dev.js +245 -89
- package/packages/tools/lib/commands/dev.js.map +1 -1
- package/packages/tools/lib/commands/dhf-draft.js +1 -1
- package/packages/tools/lib/commands/dhf-draft.js.map +1 -1
- package/packages/tools/lib/commands/dhf-lint.d.ts +10 -0
- package/packages/tools/lib/commands/dhf-lint.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf-lint.js +72 -0
- package/packages/tools/lib/commands/dhf-lint.js.map +1 -0
- package/packages/tools/lib/commands/dhf-preview.js +1 -1
- package/packages/tools/lib/commands/dhf-preview.js.map +1 -1
- package/packages/tools/lib/commands/dhf.d.ts.map +1 -1
- package/packages/tools/lib/commands/dhf.js +8 -2
- package/packages/tools/lib/commands/dhf.js.map +1 -1
- package/packages/tools/lib/commands/element.d.ts +34 -0
- package/packages/tools/lib/commands/element.d.ts.map +1 -0
- package/packages/tools/lib/commands/element.js +174 -0
- package/packages/tools/lib/commands/element.js.map +1 -0
- package/packages/tools/lib/commands/export.d.ts.map +1 -1
- package/packages/tools/lib/commands/export.js +39 -40
- package/packages/tools/lib/commands/export.js.map +1 -1
- package/packages/tools/lib/commands/generate.d.ts.map +1 -1
- package/packages/tools/lib/commands/generate.js +10 -7
- package/packages/tools/lib/commands/generate.js.map +1 -1
- package/packages/tools/lib/commands/import.d.ts.map +1 -1
- package/packages/tools/lib/commands/import.js +25 -12
- package/packages/tools/lib/commands/import.js.map +1 -1
- package/packages/tools/lib/commands/init.d.ts.map +1 -1
- package/packages/tools/lib/commands/init.js +34 -14
- package/packages/tools/lib/commands/init.js.map +1 -1
- package/packages/tools/lib/commands/inspect.d.ts +5 -0
- package/packages/tools/lib/commands/inspect.d.ts.map +1 -0
- package/packages/tools/lib/commands/inspect.js +56 -0
- package/packages/tools/lib/commands/inspect.js.map +1 -0
- package/packages/tools/lib/commands/lock.d.ts.map +1 -1
- package/packages/tools/lib/commands/lock.js +7 -2
- package/packages/tools/lib/commands/lock.js.map +1 -1
- package/packages/tools/lib/commands/ontology.d.ts.map +1 -1
- package/packages/tools/lib/commands/ontology.js +69 -116
- package/packages/tools/lib/commands/ontology.js.map +1 -1
- package/packages/tools/lib/commands/pack.d.ts +1 -1
- package/packages/tools/lib/commands/pack.d.ts.map +1 -1
- package/packages/tools/lib/commands/pack.js +20 -78
- package/packages/tools/lib/commands/pack.js.map +1 -1
- package/packages/tools/lib/commands/package.d.ts +10 -0
- package/packages/tools/lib/commands/package.d.ts.map +1 -0
- package/packages/tools/lib/commands/package.js +113 -0
- package/packages/tools/lib/commands/package.js.map +1 -0
- package/packages/tools/lib/commands/plugin.js +1 -1
- package/packages/tools/lib/commands/plugin.js.map +1 -1
- package/packages/tools/lib/commands/rules.d.ts.map +1 -1
- package/packages/tools/lib/commands/rules.js +120 -30
- package/packages/tools/lib/commands/rules.js.map +1 -1
- package/packages/tools/lib/commands/standards.d.ts +28 -0
- package/packages/tools/lib/commands/standards.d.ts.map +1 -0
- package/packages/tools/lib/commands/standards.js +203 -0
- package/packages/tools/lib/commands/standards.js.map +1 -0
- package/packages/tools/lib/commands/sysand-publish.d.ts.map +1 -1
- package/packages/tools/lib/commands/sysand-publish.js +14 -16
- package/packages/tools/lib/commands/sysand-publish.js.map +1 -1
- package/packages/tools/lib/commands/toolchain.d.ts +8 -0
- package/packages/tools/lib/commands/toolchain.d.ts.map +1 -0
- package/packages/tools/lib/commands/toolchain.js +64 -0
- package/packages/tools/lib/commands/toolchain.js.map +1 -0
- package/packages/tools/lib/commands/validate.d.ts +1 -1
- package/packages/tools/lib/commands/validate.d.ts.map +1 -1
- package/packages/tools/lib/commands/validate.js +194 -56
- package/packages/tools/lib/commands/validate.js.map +1 -1
- package/packages/tools/lib/completeness/tracker.d.ts +10 -2
- package/packages/tools/lib/completeness/tracker.d.ts.map +1 -1
- package/packages/tools/lib/completeness/tracker.js +16 -21
- package/packages/tools/lib/completeness/tracker.js.map +1 -1
- package/packages/tools/lib/conformance/baseline.d.ts +26 -0
- package/packages/tools/lib/conformance/baseline.d.ts.map +1 -0
- package/packages/tools/lib/conformance/baseline.js +170 -0
- package/packages/tools/lib/conformance/baseline.js.map +1 -0
- package/packages/tools/lib/conformance/bnf.d.ts +84 -0
- package/packages/tools/lib/conformance/bnf.d.ts.map +1 -0
- package/packages/tools/lib/conformance/bnf.js +166 -0
- package/packages/tools/lib/conformance/bnf.js.map +1 -0
- package/packages/tools/lib/conformance/corpus.d.ts +125 -0
- package/packages/tools/lib/conformance/corpus.d.ts.map +1 -0
- package/packages/tools/lib/conformance/corpus.js +190 -0
- package/packages/tools/lib/conformance/corpus.js.map +1 -0
- package/packages/tools/lib/conformance/diff-xmi.d.ts +118 -0
- package/packages/tools/lib/conformance/diff-xmi.d.ts.map +1 -0
- package/packages/tools/lib/conformance/diff-xmi.js +276 -0
- package/packages/tools/lib/conformance/diff-xmi.js.map +1 -0
- package/packages/tools/lib/conformance/generated/syside-rules.d.ts +10 -0
- package/packages/tools/lib/conformance/generated/syside-rules.d.ts.map +1 -0
- package/packages/tools/lib/conformance/generated/syside-rules.js +1142 -0
- package/packages/tools/lib/conformance/generated/syside-rules.js.map +1 -0
- package/packages/tools/lib/conformance/index.d.ts +7 -0
- package/packages/tools/lib/conformance/index.d.ts.map +1 -0
- package/packages/tools/lib/conformance/index.js +19 -0
- package/packages/tools/lib/conformance/index.js.map +1 -0
- package/packages/tools/lib/conformance/run.d.ts +117 -0
- package/packages/tools/lib/conformance/run.d.ts.map +1 -0
- package/packages/tools/lib/conformance/run.js +0 -0
- package/packages/tools/lib/conformance/run.js.map +1 -0
- package/packages/tools/lib/conformance/xmi.d.ts +45 -0
- package/packages/tools/lib/conformance/xmi.d.ts.map +1 -0
- package/packages/tools/lib/conformance/xmi.js +148 -0
- package/packages/tools/lib/conformance/xmi.js.map +1 -0
- package/packages/tools/lib/dhf/document-compiler.d.ts.map +1 -1
- package/packages/tools/lib/dhf/document-compiler.js +13 -8
- package/packages/tools/lib/dhf/document-compiler.js.map +1 -1
- package/packages/tools/lib/dhf/document-registry.d.ts +16 -2
- package/packages/tools/lib/dhf/document-registry.d.ts.map +1 -1
- package/packages/tools/lib/dhf/document-registry.js +74 -23
- package/packages/tools/lib/dhf/document-registry.js.map +1 -1
- package/packages/tools/lib/dhf/index.d.ts +3 -0
- package/packages/tools/lib/dhf/index.d.ts.map +1 -1
- package/packages/tools/lib/dhf/index.js +4 -0
- package/packages/tools/lib/dhf/index.js.map +1 -1
- package/packages/tools/lib/dhf/query-engine.d.ts +12 -1
- package/packages/tools/lib/dhf/query-engine.d.ts.map +1 -1
- package/packages/tools/lib/dhf/query-engine.js +2 -1
- package/packages/tools/lib/dhf/query-engine.js.map +1 -1
- package/packages/tools/lib/dhf/query-executor.d.ts +72 -5
- package/packages/tools/lib/dhf/query-executor.d.ts.map +1 -1
- package/packages/tools/lib/dhf/query-executor.js +471 -81
- package/packages/tools/lib/dhf/query-executor.js.map +1 -1
- package/packages/tools/lib/dhf/script-runner.js +6 -6
- package/packages/tools/lib/dhf/script-runner.js.map +1 -1
- package/packages/tools/lib/dhf/standards-block.d.ts +40 -0
- package/packages/tools/lib/dhf/standards-block.d.ts.map +1 -0
- package/packages/tools/lib/dhf/standards-block.js +223 -0
- package/packages/tools/lib/dhf/standards-block.js.map +1 -0
- package/packages/tools/lib/dhf/standards-library.d.ts +123 -0
- package/packages/tools/lib/dhf/standards-library.d.ts.map +1 -0
- package/packages/tools/lib/dhf/standards-library.js +295 -0
- package/packages/tools/lib/dhf/standards-library.js.map +1 -0
- package/packages/tools/lib/dhf/standards-report.d.ts +189 -0
- package/packages/tools/lib/dhf/standards-report.d.ts.map +1 -0
- package/packages/tools/lib/dhf/standards-report.js +384 -0
- package/packages/tools/lib/dhf/standards-report.js.map +1 -0
- package/packages/tools/lib/dhf/template-lint.d.ts +42 -0
- package/packages/tools/lib/dhf/template-lint.d.ts.map +1 -0
- package/packages/tools/lib/dhf/template-lint.js +421 -0
- package/packages/tools/lib/dhf/template-lint.js.map +1 -0
- package/packages/tools/lib/dhf/template-resolver.d.ts.map +1 -1
- package/packages/tools/lib/dhf/template-resolver.js +18 -6
- package/packages/tools/lib/dhf/template-resolver.js.map +1 -1
- package/packages/tools/lib/import/column-mapper.d.ts +2 -2
- package/packages/tools/lib/import/column-mapper.d.ts.map +1 -1
- package/packages/tools/lib/import/column-mapper.js +3 -3
- package/packages/tools/lib/import/column-mapper.js.map +1 -1
- package/packages/tools/lib/importer/cameo-importer.js +2 -2
- package/packages/tools/lib/importer/cameo-importer.js.map +1 -1
- package/packages/tools/lib/importer/ea-importer.d.ts.map +1 -1
- package/packages/tools/lib/importer/ea-importer.js +4 -3
- package/packages/tools/lib/importer/ea-importer.js.map +1 -1
- package/packages/tools/lib/importer/owl-importer.d.ts.map +1 -1
- package/packages/tools/lib/importer/owl-importer.js +2 -3
- package/packages/tools/lib/importer/owl-importer.js.map +1 -1
- package/packages/tools/lib/index.d.ts +20 -3
- package/packages/tools/lib/index.d.ts.map +1 -1
- package/packages/tools/lib/index.js +19 -2
- package/packages/tools/lib/index.js.map +1 -1
- package/packages/tools/lib/language/generated/ast.d.ts +1344 -99
- package/packages/tools/lib/language/generated/ast.d.ts.map +1 -1
- package/packages/tools/lib/language/generated/ast.js +1066 -32
- package/packages/tools/lib/language/generated/ast.js.map +1 -1
- package/packages/tools/lib/language/generated/grammar.d.ts.map +1 -1
- package/packages/tools/lib/language/generated/grammar.js +5242 -1454
- package/packages/tools/lib/language/generated/grammar.js.map +1 -1
- package/packages/tools/lib/llm/chat-engine.d.ts +4 -3
- package/packages/tools/lib/llm/chat-engine.d.ts.map +1 -1
- package/packages/tools/lib/llm/chat-engine.js +15 -12
- package/packages/tools/lib/llm/chat-engine.js.map +1 -1
- package/packages/tools/lib/llm/generate-engine.d.ts +7 -2
- package/packages/tools/lib/llm/generate-engine.d.ts.map +1 -1
- package/packages/tools/lib/llm/generate-engine.js +22 -4
- package/packages/tools/lib/llm/generate-engine.js.map +1 -1
- package/packages/tools/lib/llm/index.d.ts +1 -0
- package/packages/tools/lib/llm/index.d.ts.map +1 -1
- package/packages/tools/lib/llm/index.js +1 -0
- package/packages/tools/lib/llm/index.js.map +1 -1
- package/packages/tools/lib/llm/model-context.d.ts +2 -2
- package/packages/tools/lib/llm/model-context.d.ts.map +1 -1
- package/packages/tools/lib/llm/model-context.js +7 -13
- package/packages/tools/lib/llm/model-context.js.map +1 -1
- package/packages/tools/lib/llm/sysml-guidance.d.ts +8 -0
- package/packages/tools/lib/llm/sysml-guidance.d.ts.map +1 -0
- package/packages/tools/lib/llm/sysml-guidance.js +28 -0
- package/packages/tools/lib/llm/sysml-guidance.js.map +1 -0
- package/packages/tools/lib/lock.d.ts +14 -8
- package/packages/tools/lib/lock.d.ts.map +1 -1
- package/packages/tools/lib/lock.js +97 -108
- package/packages/tools/lib/lock.js.map +1 -1
- package/packages/tools/lib/mcp/model-loader.d.ts +3 -0
- package/packages/tools/lib/mcp/model-loader.d.ts.map +1 -1
- package/packages/tools/lib/mcp/model-loader.js +9 -5
- package/packages/tools/lib/mcp/model-loader.js.map +1 -1
- package/packages/tools/lib/mcp/tools.d.ts +3 -0
- package/packages/tools/lib/mcp/tools.d.ts.map +1 -1
- package/packages/tools/lib/mcp/tools.js +8 -9
- package/packages/tools/lib/mcp/tools.js.map +1 -1
- package/packages/tools/lib/model/activity-notation.d.ts +54 -0
- package/packages/tools/lib/model/activity-notation.d.ts.map +1 -0
- package/packages/tools/lib/model/activity-notation.js +208 -0
- package/packages/tools/lib/model/activity-notation.js.map +1 -0
- package/packages/tools/lib/model/builder.d.ts +3 -0
- package/packages/tools/lib/model/builder.d.ts.map +1 -1
- package/packages/tools/lib/model/builder.js +956 -62
- package/packages/tools/lib/model/builder.js.map +1 -1
- package/packages/tools/lib/model/config-loader.d.ts +19 -25
- package/packages/tools/lib/model/config-loader.d.ts.map +1 -1
- package/packages/tools/lib/model/config-loader.js +51 -233
- package/packages/tools/lib/model/config-loader.js.map +1 -1
- package/packages/tools/lib/model/config.d.ts +42 -213
- package/packages/tools/lib/model/config.d.ts.map +1 -1
- package/packages/tools/lib/model/config.js +11 -9
- package/packages/tools/lib/model/config.js.map +1 -1
- package/packages/tools/lib/model/effective-scope.d.ts +74 -0
- package/packages/tools/lib/model/effective-scope.d.ts.map +1 -0
- package/packages/tools/lib/model/effective-scope.js +133 -0
- package/packages/tools/lib/model/effective-scope.js.map +1 -0
- package/packages/tools/lib/model/ir-identity.d.ts +94 -0
- package/packages/tools/lib/model/ir-identity.d.ts.map +1 -0
- package/packages/tools/lib/model/ir-identity.js +178 -0
- package/packages/tools/lib/model/ir-identity.js.map +1 -0
- package/packages/tools/lib/model/kind-registry.d.ts +134 -1
- package/packages/tools/lib/model/kind-registry.d.ts.map +1 -1
- package/packages/tools/lib/model/kind-registry.js +186 -4
- package/packages/tools/lib/model/kind-registry.js.map +1 -1
- package/packages/tools/lib/model/layer-resolver.js +1 -1
- package/packages/tools/lib/model/layer-resolver.js.map +1 -1
- package/packages/tools/lib/model/manifest.d.ts +8 -0
- package/packages/tools/lib/model/manifest.d.ts.map +1 -1
- package/packages/tools/lib/model/manifest.js +3 -0
- package/packages/tools/lib/model/manifest.js.map +1 -1
- package/packages/tools/lib/model/methodology-loader.d.ts +19 -24
- package/packages/tools/lib/model/methodology-loader.d.ts.map +1 -1
- package/packages/tools/lib/model/methodology-loader.js +179 -176
- package/packages/tools/lib/model/methodology-loader.js.map +1 -1
- package/packages/tools/lib/model/methodology-resolver.d.ts +115 -0
- package/packages/tools/lib/model/methodology-resolver.d.ts.map +1 -0
- package/packages/tools/lib/model/methodology-resolver.js +317 -0
- package/packages/tools/lib/model/methodology-resolver.js.map +1 -0
- package/packages/tools/lib/model/naming.d.ts +57 -0
- package/packages/tools/lib/model/naming.d.ts.map +1 -0
- package/packages/tools/lib/model/naming.js +69 -0
- package/packages/tools/lib/model/naming.js.map +1 -0
- package/packages/tools/lib/model/native-project.d.ts +130 -0
- package/packages/tools/lib/model/native-project.d.ts.map +1 -0
- package/packages/tools/lib/model/native-project.js +580 -0
- package/packages/tools/lib/model/native-project.js.map +1 -0
- package/packages/tools/lib/model/ontology-loader.d.ts +34 -21
- package/packages/tools/lib/model/ontology-loader.d.ts.map +1 -1
- package/packages/tools/lib/model/ontology-loader.js +343 -614
- package/packages/tools/lib/model/ontology-loader.js.map +1 -1
- package/packages/tools/lib/model/package-manifest.d.ts +37 -0
- package/packages/tools/lib/model/package-manifest.d.ts.map +1 -0
- package/packages/tools/lib/model/package-manifest.js +96 -0
- package/packages/tools/lib/model/package-manifest.js.map +1 -0
- package/packages/tools/lib/model/parser-utils.d.ts +31 -0
- package/packages/tools/lib/model/parser-utils.d.ts.map +1 -1
- package/packages/tools/lib/model/parser-utils.js +89 -1
- package/packages/tools/lib/model/parser-utils.js.map +1 -1
- package/packages/tools/lib/model/paths.d.ts +10 -4
- package/packages/tools/lib/model/paths.d.ts.map +1 -1
- package/packages/tools/lib/model/paths.js +10 -4
- package/packages/tools/lib/model/paths.js.map +1 -1
- package/packages/tools/lib/model/project-conversion.d.ts +226 -0
- package/packages/tools/lib/model/project-conversion.d.ts.map +1 -0
- package/packages/tools/lib/model/project-conversion.js +946 -0
- package/packages/tools/lib/model/project-conversion.js.map +1 -0
- package/packages/tools/lib/model/relationship-legality.d.ts +27 -0
- package/packages/tools/lib/model/relationship-legality.d.ts.map +1 -1
- package/packages/tools/lib/model/relationship-legality.js.map +1 -1
- package/packages/tools/lib/model/relationship-registry.d.ts +93 -1
- package/packages/tools/lib/model/relationship-registry.d.ts.map +1 -1
- package/packages/tools/lib/model/relationship-registry.js +217 -2
- package/packages/tools/lib/model/relationship-registry.js.map +1 -1
- package/packages/tools/lib/model/semantic.d.ts +73 -0
- package/packages/tools/lib/model/semantic.d.ts.map +1 -1
- package/packages/tools/lib/model/semantic.js +6 -0
- package/packages/tools/lib/model/semantic.js.map +1 -1
- package/packages/tools/lib/model/settings-boundary.d.ts +19 -0
- package/packages/tools/lib/model/settings-boundary.d.ts.map +1 -0
- package/packages/tools/lib/model/settings-boundary.js +118 -0
- package/packages/tools/lib/model/settings-boundary.js.map +1 -0
- package/packages/tools/lib/model/short-id.js +3 -3
- package/packages/tools/lib/model/short-id.js.map +1 -1
- package/packages/tools/lib/model/source-graph.d.ts.map +1 -1
- package/packages/tools/lib/model/source-graph.js +5 -1
- package/packages/tools/lib/model/source-graph.js.map +1 -1
- package/packages/tools/lib/model/source-provenance.d.ts +112 -0
- package/packages/tools/lib/model/source-provenance.d.ts.map +1 -0
- package/packages/tools/lib/model/source-provenance.js +169 -0
- package/packages/tools/lib/model/source-provenance.js.map +1 -0
- package/packages/tools/lib/model/sysml-ir.d.ts +9 -0
- package/packages/tools/lib/model/sysml-ir.d.ts.map +1 -0
- package/packages/tools/lib/model/sysml-ir.js +105 -0
- package/packages/tools/lib/model/sysml-ir.js.map +1 -0
- package/packages/tools/lib/model/view-deriver.d.ts +10 -1
- package/packages/tools/lib/model/view-deriver.d.ts.map +1 -1
- package/packages/tools/lib/model/view-deriver.js +139 -11
- package/packages/tools/lib/model/view-deriver.js.map +1 -1
- package/packages/tools/lib/model/view-kinds.d.ts +2 -0
- package/packages/tools/lib/model/view-kinds.d.ts.map +1 -1
- package/packages/tools/lib/model/view-kinds.js +11 -0
- package/packages/tools/lib/model/view-kinds.js.map +1 -1
- package/packages/tools/lib/ontology/owl-exporter.d.ts +2 -2
- package/packages/tools/lib/ontology/owl-exporter.d.ts.map +1 -1
- package/packages/tools/lib/ontology/owl-exporter.js +12 -12
- package/packages/tools/lib/ontology/owl-exporter.js.map +1 -1
- package/packages/tools/lib/operations/ai-authoring.d.ts +24 -0
- package/packages/tools/lib/operations/ai-authoring.d.ts.map +1 -0
- package/packages/tools/lib/operations/ai-authoring.js +77 -0
- package/packages/tools/lib/operations/ai-authoring.js.map +1 -0
- package/packages/tools/lib/operations/authoring.d.ts +40 -0
- package/packages/tools/lib/operations/authoring.d.ts.map +1 -0
- package/packages/tools/lib/operations/authoring.js +56 -0
- package/packages/tools/lib/operations/authoring.js.map +1 -0
- package/packages/tools/lib/operations/index.d.ts +2 -0
- package/packages/tools/lib/operations/index.d.ts.map +1 -1
- package/packages/tools/lib/operations/index.js +2 -0
- package/packages/tools/lib/operations/index.js.map +1 -1
- package/packages/tools/lib/operations/project-snapshot.d.ts +28 -3
- package/packages/tools/lib/operations/project-snapshot.d.ts.map +1 -1
- package/packages/tools/lib/operations/project-snapshot.js +79 -30
- package/packages/tools/lib/operations/project-snapshot.js.map +1 -1
- package/packages/tools/lib/protocol/messages.d.ts +381 -12
- package/packages/tools/lib/protocol/messages.d.ts.map +1 -1
- package/packages/tools/lib/serializer/csv-io.d.ts +7 -7
- package/packages/tools/lib/serializer/csv-io.d.ts.map +1 -1
- package/packages/tools/lib/serializer/csv-io.js +11 -11
- package/packages/tools/lib/serializer/csv-io.js.map +1 -1
- package/packages/tools/lib/serializer/sysml-generator.d.ts.map +1 -1
- package/packages/tools/lib/serializer/sysml-generator.js +34 -2
- package/packages/tools/lib/serializer/sysml-generator.js.map +1 -1
- package/packages/tools/lib/server/config-resolver.d.ts +8 -4
- package/packages/tools/lib/server/config-resolver.d.ts.map +1 -1
- package/packages/tools/lib/server/config-resolver.js +25 -44
- package/packages/tools/lib/server/config-resolver.js.map +1 -1
- package/packages/tools/lib/server/conflict-policy.d.ts +44 -0
- package/packages/tools/lib/server/conflict-policy.d.ts.map +1 -0
- package/packages/tools/lib/server/conflict-policy.js +94 -0
- package/packages/tools/lib/server/conflict-policy.js.map +1 -0
- package/packages/tools/lib/server/dev-server.d.ts +32 -2
- package/packages/tools/lib/server/dev-server.d.ts.map +1 -1
- package/packages/tools/lib/server/dev-server.js +875 -54
- package/packages/tools/lib/server/dev-server.js.map +1 -1
- package/packages/tools/lib/server/element-writer.d.ts +11 -0
- package/packages/tools/lib/server/element-writer.d.ts.map +1 -0
- package/packages/tools/lib/server/element-writer.js +123 -0
- package/packages/tools/lib/server/element-writer.js.map +1 -0
- package/packages/tools/lib/server/file-watcher.d.ts +4 -1
- package/packages/tools/lib/server/file-watcher.d.ts.map +1 -1
- package/packages/tools/lib/server/file-watcher.js +17 -7
- package/packages/tools/lib/server/file-watcher.js.map +1 -1
- package/packages/tools/lib/server/mutation-domain.d.ts +22 -0
- package/packages/tools/lib/server/mutation-domain.d.ts.map +1 -0
- package/packages/tools/lib/server/mutation-domain.js +87 -0
- package/packages/tools/lib/server/mutation-domain.js.map +1 -0
- package/packages/tools/lib/server/package-source.d.ts +26 -0
- package/packages/tools/lib/server/package-source.d.ts.map +1 -0
- package/packages/tools/lib/server/package-source.js +81 -0
- package/packages/tools/lib/server/package-source.js.map +1 -0
- package/packages/tools/lib/server/package-writer.d.ts +94 -0
- package/packages/tools/lib/server/package-writer.d.ts.map +1 -0
- package/packages/tools/lib/server/package-writer.js +317 -0
- package/packages/tools/lib/server/package-writer.js.map +1 -0
- package/packages/tools/lib/server/persistor.d.ts +81 -6
- package/packages/tools/lib/server/persistor.d.ts.map +1 -1
- package/packages/tools/lib/server/persistor.js +173 -44
- package/packages/tools/lib/server/persistor.js.map +1 -1
- package/packages/tools/lib/server/relationship-writer.d.ts +41 -5
- package/packages/tools/lib/server/relationship-writer.d.ts.map +1 -1
- package/packages/tools/lib/server/relationship-writer.js +157 -13
- package/packages/tools/lib/server/relationship-writer.js.map +1 -1
- package/packages/tools/lib/server/rule-policy-writer.d.ts +40 -0
- package/packages/tools/lib/server/rule-policy-writer.d.ts.map +1 -0
- package/packages/tools/lib/server/rule-policy-writer.js +124 -0
- package/packages/tools/lib/server/rule-policy-writer.js.map +1 -0
- package/packages/tools/lib/server/runtime-budget.d.ts +14 -0
- package/packages/tools/lib/server/runtime-budget.d.ts.map +1 -0
- package/packages/tools/lib/server/runtime-budget.js +15 -0
- package/packages/tools/lib/server/runtime-budget.js.map +1 -0
- package/packages/tools/lib/server/sysml-notation.d.ts +36 -0
- package/packages/tools/lib/server/sysml-notation.d.ts.map +1 -0
- package/packages/tools/lib/server/sysml-notation.js +104 -0
- package/packages/tools/lib/server/sysml-notation.js.map +1 -0
- package/packages/tools/lib/server/view-layout-store.d.ts.map +1 -1
- package/packages/tools/lib/server/view-layout-store.js +1 -0
- package/packages/tools/lib/server/view-layout-store.js.map +1 -1
- package/packages/tools/lib/sysml-ir/generated/sysml-derivations.d.ts +9 -0
- package/packages/tools/lib/sysml-ir/generated/sysml-derivations.d.ts.map +1 -0
- package/packages/tools/lib/sysml-ir/generated/sysml-derivations.js +315 -0
- package/packages/tools/lib/sysml-ir/generated/sysml-derivations.js.map +1 -0
- package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.d.ts +5206 -0
- package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.d.ts.map +1 -0
- package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.js +1933 -0
- package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.js.map +1 -0
- package/packages/tools/lib/sysml-ir/index.d.ts +3 -0
- package/packages/tools/lib/sysml-ir/index.d.ts.map +1 -0
- package/packages/tools/lib/sysml-ir/index.js +3 -0
- package/packages/tools/lib/sysml-ir/index.js.map +1 -0
- package/packages/tools/lib/sysml-ir/ir.d.ts +50 -0
- package/packages/tools/lib/sysml-ir/ir.d.ts.map +1 -0
- package/packages/tools/lib/sysml-ir/ir.js +2 -0
- package/packages/tools/lib/sysml-ir/ir.js.map +1 -0
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.d.ts +3 -0
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.d.ts.map +1 -0
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.js +97 -0
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.js.map +1 -0
- package/packages/tools/lib/sysmlc/index.d.ts +2 -0
- package/packages/tools/lib/sysmlc/index.d.ts.map +1 -0
- package/packages/tools/lib/sysmlc/index.js +7 -0
- package/packages/tools/lib/sysmlc/index.js.map +1 -0
- package/packages/tools/lib/sysmlc/server.d.ts +29 -0
- package/packages/tools/lib/sysmlc/server.d.ts.map +1 -0
- package/packages/tools/lib/sysmlc/server.js +168 -0
- package/packages/tools/lib/sysmlc/server.js.map +1 -0
- package/packages/tools/lib/toolchain/default-registry.d.ts +12 -0
- package/packages/tools/lib/toolchain/default-registry.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/default-registry.js +28 -0
- package/packages/tools/lib/toolchain/default-registry.js.map +1 -0
- package/packages/tools/lib/toolchain/diagnostic.d.ts +57 -0
- package/packages/tools/lib/toolchain/diagnostic.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/diagnostic.js +69 -0
- package/packages/tools/lib/toolchain/diagnostic.js.map +1 -0
- package/packages/tools/lib/toolchain/effective.d.ts +36 -0
- package/packages/tools/lib/toolchain/effective.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/effective.js +91 -0
- package/packages/tools/lib/toolchain/effective.js.map +1 -0
- package/packages/tools/lib/toolchain/index.d.ts +11 -0
- package/packages/tools/lib/toolchain/index.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/index.js +21 -0
- package/packages/tools/lib/toolchain/index.js.map +1 -0
- package/packages/tools/lib/toolchain/lowering.d.ts +63 -0
- package/packages/tools/lib/toolchain/lowering.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/lowering.js +100 -0
- package/packages/tools/lib/toolchain/lowering.js.map +1 -0
- package/packages/tools/lib/toolchain/operations.d.ts +87 -0
- package/packages/tools/lib/toolchain/operations.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/operations.js +111 -0
- package/packages/tools/lib/toolchain/operations.js.map +1 -0
- package/packages/tools/lib/toolchain/process.d.ts +45 -0
- package/packages/tools/lib/toolchain/process.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/process.js +125 -0
- package/packages/tools/lib/toolchain/process.js.map +1 -0
- package/packages/tools/lib/toolchain/protocol.d.ts +122 -0
- package/packages/tools/lib/toolchain/protocol.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/protocol.js +74 -0
- package/packages/tools/lib/toolchain/protocol.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/internal-kpar.d.ts +9 -0
- package/packages/tools/lib/toolchain/providers/internal-kpar.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/internal-kpar.js +84 -0
- package/packages/tools/lib/toolchain/providers/internal-kpar.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/internal.d.ts +33 -0
- package/packages/tools/lib/toolchain/providers/internal.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/internal.js +286 -0
- package/packages/tools/lib/toolchain/providers/internal.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/sysand.d.ts +12 -0
- package/packages/tools/lib/toolchain/providers/sysand.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/sysand.js +110 -0
- package/packages/tools/lib/toolchain/providers/sysand.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/syside.d.ts +24 -0
- package/packages/tools/lib/toolchain/providers/syside.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/syside.js +208 -0
- package/packages/tools/lib/toolchain/providers/syside.js.map +1 -0
- package/packages/tools/lib/toolchain/registry.d.ts +192 -0
- package/packages/tools/lib/toolchain/registry.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/registry.js +130 -0
- package/packages/tools/lib/toolchain/registry.js.map +1 -0
- package/packages/tools/lib/toolchain/schema.d.ts +30 -0
- package/packages/tools/lib/toolchain/schema.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/schema.js +112 -0
- package/packages/tools/lib/toolchain/schema.js.map +1 -0
- package/packages/tools/lib/toolchain/sysmlc-client.d.ts +77 -0
- package/packages/tools/lib/toolchain/sysmlc-client.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/sysmlc-client.js +0 -0
- package/packages/tools/lib/toolchain/sysmlc-client.js.map +1 -0
- package/packages/tools/lib/validator/architecture-validator.d.ts +8 -1
- package/packages/tools/lib/validator/architecture-validator.d.ts.map +1 -1
- package/packages/tools/lib/validator/architecture-validator.js +25 -1
- package/packages/tools/lib/validator/architecture-validator.js.map +1 -1
- package/packages/tools/lib/validator/behavior-validator.d.ts +1 -1
- package/packages/tools/lib/validator/behavior-validator.js +1 -1
- package/packages/tools/lib/validator/builtin-rules.d.ts +16 -0
- package/packages/tools/lib/validator/builtin-rules.d.ts.map +1 -0
- package/packages/tools/lib/validator/builtin-rules.js +62 -0
- package/packages/tools/lib/validator/builtin-rules.js.map +1 -0
- package/packages/tools/lib/validator/constraint-eval.d.ts +31 -0
- package/packages/tools/lib/validator/constraint-eval.d.ts.map +1 -1
- package/packages/tools/lib/validator/constraint-eval.js +164 -7
- package/packages/tools/lib/validator/constraint-eval.js.map +1 -1
- package/packages/tools/lib/validator/constraint-loader.d.ts +22 -4
- package/packages/tools/lib/validator/constraint-loader.d.ts.map +1 -1
- package/packages/tools/lib/validator/constraint-loader.js +100 -27
- package/packages/tools/lib/validator/constraint-loader.js.map +1 -1
- package/packages/tools/lib/validator/rule-engine.d.ts +2 -1
- package/packages/tools/lib/validator/rule-engine.d.ts.map +1 -1
- package/packages/tools/lib/validator/rule-engine.js +56 -5
- package/packages/tools/lib/validator/rule-engine.js.map +1 -1
- package/packages/tools/lib/validator/sysml-constraints.d.ts +64 -0
- package/packages/tools/lib/validator/sysml-constraints.d.ts.map +1 -0
- package/packages/tools/lib/validator/sysml-constraints.js +251 -0
- package/packages/tools/lib/validator/sysml-constraints.js.map +1 -0
- package/packages/tools/lib/validator/types.d.ts +33 -0
- package/packages/tools/lib/validator/types.d.ts.map +1 -1
- package/packages/tools/lib/version.d.ts +2 -0
- package/packages/tools/lib/version.d.ts.map +1 -0
- package/packages/tools/lib/version.js +26 -0
- package/packages/tools/lib/version.js.map +1 -0
- package/packages/tools/src/grammar/memo-sysml.langium +517 -41
- package/packages/tools/lib/model/dimension-filter.d.ts +0 -33
- package/packages/tools/lib/model/dimension-filter.d.ts.map +0 -1
- package/packages/tools/lib/model/dimension-filter.js +0 -57
- package/packages/tools/lib/model/dimension-filter.js.map +0 -1
- package/packages/tools/lib/model/toolchain.d.ts +0 -12
- package/packages/tools/lib/model/toolchain.d.ts.map +0 -1
- package/packages/tools/lib/model/toolchain.js +0 -92
- package/packages/tools/lib/model/toolchain.js.map +0 -1
|
@@ -21,13 +21,26 @@
|
|
|
21
21
|
// - ActionUsage supports composite actions with nested actions
|
|
22
22
|
// - FlowConnectionUsage → MemoRelationship of type "flow" with flowItem
|
|
23
23
|
// - SuccessionUsage → MemoRelationship pairs of type "succession"
|
|
24
|
-
// - AllocateUsage → MemoRelationship of type "allocateTo"
|
|
25
24
|
// - ItemDefinition → MemoElement with construct "item"
|
|
25
|
+
//
|
|
26
|
+
// Language-native trace relations:
|
|
27
|
+
// - AllocateUsage → MemoRelationship "allocatedTo"
|
|
28
|
+
// - SatisfyRequirementUsage → MemoRelationship "satisfiedBy"
|
|
29
|
+
// - RequirementVerificationMember → MemoRelationship "verifiedBy"
|
|
30
|
+
// Each is the SAME edge the corresponding MEMO `connection def` produces —
|
|
31
|
+
// see LANGUAGE_NATIVE_RELATIONS. A model may use either spelling and the
|
|
32
|
+
// graph is identical, which is what makes the migration off the private
|
|
33
|
+
// connection defs reversible one file at a time.
|
|
26
34
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
35
|
import { createHash } from 'node:crypto';
|
|
36
|
+
import { AstUtils } from 'langium';
|
|
37
|
+
import { isRequirementVerificationMember, isSatisfyRequirementUsage, isPerformActionUsage, isIncludeUseCaseUsage, isExhibitStateUsage, isFramedConcernMember, isSubjectMember, isDependency, isVariantMember, isActorMember, } from '../language/generated/ast.js';
|
|
28
38
|
import { PackageRegistry } from './package-registry.js';
|
|
29
39
|
import { assignSequentialShortIds, kindToPrefix } from './short-id.js';
|
|
40
|
+
import { LANGUAGE_NATIVE_RELATIONS, REFINEMENT_METADATA, pascalToCamelCase } from './relationship-registry.js';
|
|
30
41
|
import { indexKinds, kindConformsTo } from './relationship-legality.js';
|
|
42
|
+
import { CONTROL_KIND_METACLASS } from './activity-notation.js';
|
|
43
|
+
import { toModelType } from './naming.js';
|
|
31
44
|
let relationshipCounter = 0;
|
|
32
45
|
/**
|
|
33
46
|
* Resolve a kind definition using registry-first, config-fallback strategy.
|
|
@@ -55,8 +68,10 @@ function resolveKindDef(typeName, config, registries) {
|
|
|
55
68
|
}
|
|
56
69
|
}
|
|
57
70
|
}
|
|
58
|
-
//
|
|
59
|
-
|
|
71
|
+
// There is no config fallback. Kinds come from the ontology the project
|
|
72
|
+
// resolves; a YAML `kinds:` block used to be able to declare one, which
|
|
73
|
+
// meant a settings file could invent a type the ontology never defined.
|
|
74
|
+
const kinds = {};
|
|
60
75
|
const kindDef = kinds[typeName];
|
|
61
76
|
if (kindDef) {
|
|
62
77
|
return { kindDef, resolvedKind: typeName };
|
|
@@ -83,13 +98,14 @@ export function buildMemoModel(documents, config, parseErrors = [], registries)
|
|
|
83
98
|
const deferredFlows = [];
|
|
84
99
|
const deferredSuccessions = [];
|
|
85
100
|
const deferredAllocates = [];
|
|
101
|
+
const deferredBindings = [];
|
|
86
102
|
// Phase 1: Build package registry from all documents
|
|
87
103
|
const registry = new PackageRegistry();
|
|
88
104
|
registry.buildFromDocuments(documents);
|
|
89
105
|
// Phase 2: Extract elements from all documents (populates registry)
|
|
90
106
|
for (const { document, filePath } of documents) {
|
|
91
107
|
const model = document.parseResult.value;
|
|
92
|
-
extractFromModel(model, filePath, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, errors, registry, registries);
|
|
108
|
+
extractFromModel(model, filePath, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries);
|
|
93
109
|
}
|
|
94
110
|
// Phase 3: Resolve connections using the registry (all elements now known)
|
|
95
111
|
const allElementIds = new Set(elements.keys());
|
|
@@ -98,7 +114,11 @@ export function buildMemoModel(documents, config, parseErrors = [], registries)
|
|
|
98
114
|
}
|
|
99
115
|
// Phase 3b: Resolve flow connections
|
|
100
116
|
for (const { flow, filePath, packageName, parentActionId } of deferredFlows) {
|
|
101
|
-
resolveFlowConnection(flow, filePath, packageName, parentActionId, relationships, allElementIds);
|
|
117
|
+
resolveFlowConnection(flow, filePath, packageName, parentActionId, relationships, allElementIds, elements);
|
|
118
|
+
}
|
|
119
|
+
// Phase 3b2: Resolve port delegations
|
|
120
|
+
for (const { binding, filePath, packageName } of deferredBindings) {
|
|
121
|
+
resolveBinding(binding, filePath, packageName, relationships, allElementIds, elements);
|
|
102
122
|
}
|
|
103
123
|
// Phase 3c: Resolve successions
|
|
104
124
|
for (const { succession, filePath, packageName, parentActionId } of deferredSuccessions) {
|
|
@@ -106,8 +126,75 @@ export function buildMemoModel(documents, config, parseErrors = [], registries)
|
|
|
106
126
|
}
|
|
107
127
|
// Phase 3d: Resolve allocations
|
|
108
128
|
for (const { allocate, filePath, packageName } of deferredAllocates) {
|
|
109
|
-
resolveAllocate(allocate, filePath, packageName, elements, relationships, registry, allElementIds);
|
|
129
|
+
resolveAllocate(allocate, filePath, packageName, elements, relationships, registry, allElementIds, registries?.relationshipRegistry);
|
|
130
|
+
}
|
|
131
|
+
// Phase 3e: Resolve the native requirement relations. Unlike connections
|
|
132
|
+
// these are not package members — a `satisfy` sits in the body of the part
|
|
133
|
+
// that is the design context, and a `verify` in the body of the case that
|
|
134
|
+
// does the verifying — so they are found by walking containment rather than
|
|
135
|
+
// by the package-member switch, and their context comes from their owner.
|
|
136
|
+
for (const { document, filePath } of documents) {
|
|
137
|
+
resolveNativeTraceUsages(document.parseResult.value, filePath, relationships, registry, allElementIds);
|
|
138
|
+
}
|
|
139
|
+
// Phase 3f: Synthesize containment edges from native nesting. A natively
|
|
140
|
+
// nested part carries its parent in `owner` (set during extraction); MEMO's
|
|
141
|
+
// consumers read containment as a `composes` relationship (parent → child),
|
|
142
|
+
// so emit one per nesting. A model that nests natively then looks identical
|
|
143
|
+
// to one that wrote `Composes`, which is what lets R10-S7 delete the
|
|
144
|
+
// relationship without the containment vanishing. Ports carry `owner` too,
|
|
145
|
+
// so this is confined to part-to-part nesting.
|
|
146
|
+
for (const el of elements.values()) {
|
|
147
|
+
if (el.construct !== 'part' || !el.owner)
|
|
148
|
+
continue;
|
|
149
|
+
const parent = elements.get(el.owner);
|
|
150
|
+
if (!parent || parent.construct !== 'part')
|
|
151
|
+
continue;
|
|
152
|
+
relationships.push({
|
|
153
|
+
id: `rel-${++relationshipCounter}`,
|
|
154
|
+
type: 'composes',
|
|
155
|
+
sourceId: el.owner,
|
|
156
|
+
sourceEnd: 'parent',
|
|
157
|
+
targetId: el.id,
|
|
158
|
+
targetEnd: 'child',
|
|
159
|
+
file: el.file,
|
|
160
|
+
named: false,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// A nested action carries its parent in `parentAction` rather than
|
|
164
|
+
// `owner` (the two are set by separate extraction paths), and
|
|
165
|
+
// CR-ONT-065/066 already treat an action-typed end as a legitimate
|
|
166
|
+
// composes participant alongside parts — a functional decomposition
|
|
167
|
+
// (`action fnParent { action fnChild : SystemFunction { ... } }`) needs
|
|
168
|
+
// the same synthesis or a natively nested function tree loses the
|
|
169
|
+
// `composes` edges DSM and traceability consumers read, the exact
|
|
170
|
+
// silent-drop shape R10-S7 exists to close, not open. Every action
|
|
171
|
+
// usage nests some way — a flow step under its flow, a control node
|
|
172
|
+
// under its action — so this is not confined to decomposition the way
|
|
173
|
+
// the part path is; a nested action's owner IS its containing action
|
|
174
|
+
// for every shape the grammar produces, so there is no narrower
|
|
175
|
+
// predicate to gate this on without re-deriving one from AST shape
|
|
176
|
+
// that `parentAction` already erased.
|
|
177
|
+
for (const el of elements.values()) {
|
|
178
|
+
if (el.construct !== 'action' || !el.parentAction)
|
|
179
|
+
continue;
|
|
180
|
+
const parent = elements.get(el.parentAction);
|
|
181
|
+
if (!parent || parent.construct !== 'action')
|
|
182
|
+
continue;
|
|
183
|
+
relationships.push({
|
|
184
|
+
id: `rel-${++relationshipCounter}`,
|
|
185
|
+
type: 'composes',
|
|
186
|
+
sourceId: el.parentAction,
|
|
187
|
+
sourceEnd: 'parent',
|
|
188
|
+
targetId: el.id,
|
|
189
|
+
targetEnd: 'child',
|
|
190
|
+
file: el.file,
|
|
191
|
+
named: false,
|
|
192
|
+
});
|
|
110
193
|
}
|
|
194
|
+
// Keep ownership of a declaration separate from ownership of the type that
|
|
195
|
+
// classifies it. A project usage of `Hazard` is editable project content;
|
|
196
|
+
// its classifier is a read-only ontology definition.
|
|
197
|
+
applySemanticProvenance(elements, relationships, registries);
|
|
111
198
|
// Build indexes
|
|
112
199
|
const elementsByKind = new Map();
|
|
113
200
|
const elementsByLayer = new Map();
|
|
@@ -132,7 +219,11 @@ export function buildMemoModel(documents, config, parseErrors = [], registries)
|
|
|
132
219
|
const idToShortId = assignSequentialShortIds(prefix, prefixElements.map(e => e.id));
|
|
133
220
|
for (const el of prefixElements) {
|
|
134
221
|
el.shortId = idToShortId.get(el.id);
|
|
135
|
-
|
|
222
|
+
// `uuid` is part of the ontology's identification core, so a model
|
|
223
|
+
// may author it. An authored value wins: it is the whole point of
|
|
224
|
+
// writing one — the element keeps its identity across a file move
|
|
225
|
+
// or an id change, which the derived hash cannot survive.
|
|
226
|
+
el.uuid = el.attributes.uuid?.trim() || stableElementUuid(el);
|
|
136
227
|
}
|
|
137
228
|
}
|
|
138
229
|
// Phase 4: Validate relationship end types (warnings only).
|
|
@@ -190,6 +281,7 @@ export function buildMemoModel(documents, config, parseErrors = [], registries)
|
|
|
190
281
|
elements,
|
|
191
282
|
relationships,
|
|
192
283
|
errors,
|
|
284
|
+
packages: collectPackages(registry),
|
|
193
285
|
elementsByKind,
|
|
194
286
|
elementsByLayer,
|
|
195
287
|
relationshipsByType,
|
|
@@ -197,6 +289,69 @@ export function buildMemoModel(documents, config, parseErrors = [], registries)
|
|
|
197
289
|
incoming,
|
|
198
290
|
};
|
|
199
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* The declared packages, in the shape the model carries them.
|
|
294
|
+
*
|
|
295
|
+
* Read from the registry rather than from element membership so a package that
|
|
296
|
+
* declares nothing is still reported: an explorer builds its containment tree
|
|
297
|
+
* from this list, and a newly created package has no members yet by definition.
|
|
298
|
+
*/
|
|
299
|
+
function collectPackages(registry) {
|
|
300
|
+
const packages = [];
|
|
301
|
+
for (const entry of registry.getPackages().values()) {
|
|
302
|
+
const separator = entry.qualifiedName.lastIndexOf('::');
|
|
303
|
+
packages.push({
|
|
304
|
+
qualifiedName: entry.qualifiedName,
|
|
305
|
+
name: separator === -1 ? entry.qualifiedName : entry.qualifiedName.slice(separator + 2),
|
|
306
|
+
...(separator === -1 ? {} : { parent: entry.qualifiedName.slice(0, separator) }),
|
|
307
|
+
file: entry.file,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return packages.sort((a, b) => a.qualifiedName.localeCompare(b.qualifiedName));
|
|
311
|
+
}
|
|
312
|
+
function applySemanticProvenance(elements, relationships, registries) {
|
|
313
|
+
const table = registries?.provenance;
|
|
314
|
+
if (!table)
|
|
315
|
+
return;
|
|
316
|
+
const entryFor = (kind) => registries?.kindRegistry?.getKind(kind)
|
|
317
|
+
?? registries?.kindRegistry?.getKind(kind.split('::').pop() ?? kind);
|
|
318
|
+
const classifierFor = (kind) => {
|
|
319
|
+
const entry = entryFor(kind);
|
|
320
|
+
if (!entry?.qualifiedName)
|
|
321
|
+
return undefined;
|
|
322
|
+
return {
|
|
323
|
+
qualifiedName: entry.qualifiedName,
|
|
324
|
+
shortName: entry.name,
|
|
325
|
+
provenance: entry.sourceFile ? table.lookup(entry.sourceFile) : undefined,
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
const classifierChainFor = (kind) => {
|
|
329
|
+
const chain = [];
|
|
330
|
+
const seen = new Set();
|
|
331
|
+
let entry = entryFor(kind);
|
|
332
|
+
while (entry?.qualifiedName && !seen.has(entry.qualifiedName)) {
|
|
333
|
+
seen.add(entry.qualifiedName);
|
|
334
|
+
chain.push({
|
|
335
|
+
qualifiedName: entry.qualifiedName,
|
|
336
|
+
shortName: entry.name,
|
|
337
|
+
provenance: entry.sourceFile ? table.lookup(entry.sourceFile) : undefined,
|
|
338
|
+
});
|
|
339
|
+
entry = entry.superType ? entryFor(entry.superType) : undefined;
|
|
340
|
+
}
|
|
341
|
+
return chain.length > 0 ? chain : undefined;
|
|
342
|
+
};
|
|
343
|
+
const declarationFor = (file, kind) => ({
|
|
344
|
+
declaration: table.lookupOrProject(file),
|
|
345
|
+
classifier: kind ? classifierFor(kind) : undefined,
|
|
346
|
+
classifierChain: kind ? classifierChainFor(kind) : undefined,
|
|
347
|
+
});
|
|
348
|
+
for (const element of elements.values()) {
|
|
349
|
+
element.provenance = declarationFor(element.file, element.kind);
|
|
350
|
+
}
|
|
351
|
+
for (const relationship of relationships) {
|
|
352
|
+
relationship.provenance = declarationFor(relationship.file, relationship.type);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
200
355
|
/**
|
|
201
356
|
* Derive a UUID from source identity, rather than allocating a random value on
|
|
202
357
|
* every compilation. This is the machine identity; `shortId` is the compact
|
|
@@ -213,19 +368,19 @@ function stableElementUuid(element) {
|
|
|
213
368
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
214
369
|
}
|
|
215
370
|
// ─── AST Walking ────────────────────────────────────────────────────────────
|
|
216
|
-
function extractFromModel(model, filePath, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, errors, registry, registries) {
|
|
371
|
+
function extractFromModel(model, filePath, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries) {
|
|
217
372
|
for (const member of model.members) {
|
|
218
373
|
if (member.$type === 'PackageDeclaration') {
|
|
219
|
-
extractFromPackage(member, filePath, '', config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, errors, registry, registries);
|
|
374
|
+
extractFromPackage(member, filePath, '', config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries);
|
|
220
375
|
}
|
|
221
376
|
}
|
|
222
377
|
}
|
|
223
|
-
function extractFromPackage(pkg, filePath, parentPackage, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, errors, registry, registries) {
|
|
378
|
+
function extractFromPackage(pkg, filePath, parentPackage, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries) {
|
|
224
379
|
const packageName = parentPackage ? `${parentPackage}::${pkg.name}` : pkg.name;
|
|
225
380
|
for (const member of pkg.members) {
|
|
226
381
|
switch (member.$type) {
|
|
227
382
|
case 'PackageDeclaration':
|
|
228
|
-
extractFromPackage(member, filePath, packageName, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, errors, registry, registries);
|
|
383
|
+
extractFromPackage(member, filePath, packageName, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries);
|
|
229
384
|
break;
|
|
230
385
|
case 'PartUsage':
|
|
231
386
|
extractUsage(member, 'part', filePath, packageName, config, elements, registry, registries);
|
|
@@ -269,6 +424,43 @@ function extractFromPackage(pkg, filePath, parentPackage, config, elements, defe
|
|
|
269
424
|
packageName,
|
|
270
425
|
});
|
|
271
426
|
break;
|
|
427
|
+
case 'BindingUsage':
|
|
428
|
+
// Port delegation. Deferred for the same reason as flows: both
|
|
429
|
+
// ends are dotted paths that only resolve once every nested
|
|
430
|
+
// port is an element.
|
|
431
|
+
deferredBindings.push({
|
|
432
|
+
binding: member,
|
|
433
|
+
filePath,
|
|
434
|
+
packageName,
|
|
435
|
+
});
|
|
436
|
+
break;
|
|
437
|
+
case 'FlowConnectionUsage':
|
|
438
|
+
// A flow between two action usages declared side by side in a
|
|
439
|
+
// package has no enclosing action, so parentActionId is unset
|
|
440
|
+
// and the endpoints resolve against the package scope.
|
|
441
|
+
deferredFlows.push({
|
|
442
|
+
flow: member,
|
|
443
|
+
filePath,
|
|
444
|
+
packageName,
|
|
445
|
+
});
|
|
446
|
+
break;
|
|
447
|
+
case 'MessageUsage':
|
|
448
|
+
// `Message : FlowUsage`: native messages deliberately lower
|
|
449
|
+
// through the same path as MEMO's flow-shaped compatibility
|
|
450
|
+
// vocabulary, so consumers retain one trace-edge spelling.
|
|
451
|
+
deferredFlows.push({
|
|
452
|
+
flow: member,
|
|
453
|
+
filePath,
|
|
454
|
+
packageName,
|
|
455
|
+
});
|
|
456
|
+
break;
|
|
457
|
+
case 'SuccessionUsage':
|
|
458
|
+
deferredSuccessions.push({
|
|
459
|
+
succession: member,
|
|
460
|
+
filePath,
|
|
461
|
+
packageName,
|
|
462
|
+
});
|
|
463
|
+
break;
|
|
272
464
|
case 'AllocateUsage':
|
|
273
465
|
deferredAllocates.push({
|
|
274
466
|
allocate: member,
|
|
@@ -276,9 +468,30 @@ function extractFromPackage(pkg, filePath, parentPackage, config, elements, defe
|
|
|
276
468
|
packageName,
|
|
277
469
|
});
|
|
278
470
|
break;
|
|
471
|
+
// ─── Native declarations (plan §8) ──────────────────────────
|
|
472
|
+
//
|
|
473
|
+
// `actor u : User;`, `stakeholder s : Stakeholder;` and
|
|
474
|
+
// `concern c : Concern;` declare the same elements `part u : User;`
|
|
475
|
+
// declares — same id, same kind, same attributes, same doc. Only
|
|
476
|
+
// the metaclass differs, and the metaclass is what makes them
|
|
477
|
+
// legible to a conforming tool. Routing them through extractUsage
|
|
478
|
+
// is what keeps the migration in step 3 a spelling change rather
|
|
479
|
+
// than a content change.
|
|
480
|
+
case 'ActorMember':
|
|
481
|
+
extractUsage(member, 'actor', filePath, packageName, config, elements, registry, registries);
|
|
482
|
+
break;
|
|
483
|
+
case 'StakeholderMember':
|
|
484
|
+
extractUsage(member, 'stakeholder', filePath, packageName, config, elements, registry, registries);
|
|
485
|
+
break;
|
|
486
|
+
case 'ConcernUsage':
|
|
487
|
+
extractUsage(member, 'concern', filePath, packageName, config, elements, registry, registries);
|
|
488
|
+
break;
|
|
489
|
+
case 'TransitionUsage':
|
|
490
|
+
extractTransition(member, filePath, packageName, config, elements, registry, registries);
|
|
491
|
+
break;
|
|
279
492
|
// ─── Definition members ─────────────────────────────────────
|
|
280
493
|
case 'ActionDefinition':
|
|
281
|
-
extractActionDefinition(member, filePath, packageName, config, elements, registry);
|
|
494
|
+
extractActionDefinition(member, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries);
|
|
282
495
|
break;
|
|
283
496
|
case 'ItemDefinition':
|
|
284
497
|
extractItemDefinition(member, filePath, packageName, config, elements, registry, registries);
|
|
@@ -303,24 +516,54 @@ function extractUsage(usage, construct, filePath, packageName, config, elements,
|
|
|
303
516
|
: { kindDef: undefined, resolvedKind: 'Unknown' };
|
|
304
517
|
const attributes = extractAttributes(usage.body);
|
|
305
518
|
const doc = extractDocComment(usage.body);
|
|
306
|
-
//
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
//
|
|
519
|
+
// A view's `expose <path>;` members declare its element membership
|
|
520
|
+
// natively — SysML v2's own visibility mechanism, in place of the MEMO
|
|
521
|
+
// `IncludedIn` relationship. Collected as a comma-separated attribute so
|
|
522
|
+
// `resolveViewElementIds` in view-deriver.ts can resolve each path
|
|
523
|
+
// against the model the same way it resolves `selectionQuery.*`.
|
|
524
|
+
if (construct === 'view') {
|
|
525
|
+
const exposePaths = (usage.body || [])
|
|
526
|
+
.filter(member => member.$type === 'ExposeMember')
|
|
527
|
+
.map(member => member.path);
|
|
528
|
+
if (exposePaths.length > 0) {
|
|
529
|
+
attributes['expose'] = exposePaths.join(',');
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// Nested part members that are view METADATA, not containment: reference
|
|
533
|
+
// bindings (`part viewpoint :> vp;`) and the `:>>` redefinition of an
|
|
534
|
+
// inherited feature whose body is attributes (`part :>> selectionQuery
|
|
535
|
+
// { ... }`). These are flattened onto the owner as plain / prefixed
|
|
536
|
+
// attributes so SysML-modelled views expose their viewpoint binding and
|
|
537
|
+
// selection-query metadata to consumers. A typed nested part is NOT metadata
|
|
538
|
+
// — it is real containment and is extracted as its own element below.
|
|
310
539
|
for (const member of usage.body || []) {
|
|
311
540
|
if (member.$type !== 'PartMember')
|
|
312
541
|
continue;
|
|
313
542
|
const pm = member;
|
|
314
543
|
if (pm.boundRef && pm.name) {
|
|
544
|
+
// Two shapes land here. `part viewpointDefinition :> vp;` names the
|
|
545
|
+
// feature in `name` and the value in `boundRef`. The subsetting
|
|
546
|
+
// form for a multi-valued feature —
|
|
547
|
+
// `part vpLogical :> viewpointDefinition = someViewpoint;` — puts
|
|
548
|
+
// the FEATURE in `boundRef` and the value in `subsetValue`, and its
|
|
549
|
+
// member name is arbitrary. Attribute it to the feature it subsets,
|
|
550
|
+
// or a view governed by three viewpoints would surface as three
|
|
551
|
+
// unrelated attributes nothing reads.
|
|
552
|
+
const key = pm.subsetValue ? pm.boundRef : pm.name;
|
|
553
|
+
const value = pm.subsetValue ?? pm.boundRef;
|
|
315
554
|
// A feature with multiplicity may be rebound more than once. Keep
|
|
316
555
|
// every binding as a comma-separated value so view conformance can
|
|
317
556
|
// model one view against several viewpoints without cloning it.
|
|
318
|
-
const previous = attributes[
|
|
319
|
-
attributes[
|
|
320
|
-
? `${previous},${pm.boundRef}`
|
|
321
|
-
: pm.boundRef;
|
|
557
|
+
const previous = attributes[key];
|
|
558
|
+
attributes[key] = previous ? `${previous},${value}` : value;
|
|
322
559
|
}
|
|
323
|
-
else if (pm.body && pm.name) {
|
|
560
|
+
else if (!pm.type && pm.body && pm.name) {
|
|
561
|
+
// R10-S3 guard: an UNTYPED nested part with an attribute body is
|
|
562
|
+
// view metadata — the `part :>> selectionQuery { ... }` (or the
|
|
563
|
+
// un-redefined `part selectionQuery { ... }`) that view derivation
|
|
564
|
+
// reads as `selectionQuery.*` attributes. It carries no kind, so it
|
|
565
|
+
// is not a contained element. Flatten it; a TYPED nested part
|
|
566
|
+
// (`part valve : Valve`) is real containment and is extracted below.
|
|
324
567
|
const nested = extractAttributes(pm.body);
|
|
325
568
|
for (const [k, v] of Object.entries(nested)) {
|
|
326
569
|
attributes[`${pm.name}.${k}`] = v;
|
|
@@ -343,30 +586,124 @@ function extractUsage(usage, construct, filePath, packageName, config, elements,
|
|
|
343
586
|
// Port-specific fields
|
|
344
587
|
if (construct === 'port') {
|
|
345
588
|
const portNode = usage;
|
|
589
|
+
const directedItems = (usage.body || [])
|
|
590
|
+
.filter(member => member.$type === 'ItemUsage' && !!member.direction)
|
|
591
|
+
.map(member => member);
|
|
592
|
+
const itemDirections = new Set(directedItems.map(item => item.direction));
|
|
346
593
|
element.portSpec = {
|
|
347
594
|
type: portNode.type,
|
|
348
|
-
direction: portNode.direction,
|
|
595
|
+
direction: (portNode.direction ?? (itemDirections.size === 1 ? directedItems[0]?.direction : undefined)),
|
|
349
596
|
isConjugated: portNode.isConjugated ?? false,
|
|
350
597
|
};
|
|
598
|
+
element.parameters = directedItems
|
|
599
|
+
.map(feature => {
|
|
600
|
+
return {
|
|
601
|
+
name: feature.name,
|
|
602
|
+
direction: feature.direction,
|
|
603
|
+
type: feature.type || 'Item',
|
|
604
|
+
};
|
|
605
|
+
});
|
|
351
606
|
}
|
|
352
607
|
elements.set(id, element);
|
|
353
608
|
registry.registerElement(id, packageName);
|
|
609
|
+
// A port's body may declare further ports. Recurse only after the parent is
|
|
610
|
+
// in the map, so the child's `owner` points at an element that exists.
|
|
611
|
+
if (construct === 'port') {
|
|
612
|
+
extractDefinitionPorts(usage, filePath, packageName, config, elements, registry, registries);
|
|
613
|
+
}
|
|
614
|
+
// A part's body may nest further parts. SysML v2 expresses containment by
|
|
615
|
+
// nesting; MEMO historically expressed it with a `Composes` connection, and
|
|
616
|
+
// the two must yield the same model. Extract each nested part as its own
|
|
617
|
+
// element with `owner` set — exactly as a nested port is — only after the
|
|
618
|
+
// parent is in the map. buildMemoModel synthesizes the `composes` edge from
|
|
619
|
+
// the resulting `owner` chain.
|
|
620
|
+
//
|
|
621
|
+
// A part usage may also declare its OWN boundary ports directly in its
|
|
622
|
+
// body (`part x : T { in port p : DataPort; }`), distinct from a nested
|
|
623
|
+
// part's ports and from any ports the type `T` declares at the def level
|
|
624
|
+
// (that path is `extractDefinitionPorts` at package scope, line ~668).
|
|
625
|
+
// Without this, an inline-authored port silently has no element: it
|
|
626
|
+
// parses, every relationship endpoint referencing it resolves to a
|
|
627
|
+
// dangling id, and nothing downstream reports why.
|
|
628
|
+
if (construct === 'part') {
|
|
629
|
+
extractNestedParts(usage, filePath, packageName, config, elements, registry, registries);
|
|
630
|
+
extractDefinitionPorts(usage, filePath, packageName, config, elements, registry, registries);
|
|
631
|
+
}
|
|
632
|
+
// A native `transition` lives inside the state machine that owns it, which
|
|
633
|
+
// is where the language puts it and where MEMO's `part def Transition`
|
|
634
|
+
// never could. Extract it from the state usage's body so the two spellings
|
|
635
|
+
// yield the same element set.
|
|
636
|
+
for (const member of usage.body || []) {
|
|
637
|
+
if (member.$type === 'TransitionUsage') {
|
|
638
|
+
extractTransition(member, filePath, packageName, config, elements, registry, registries);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Extract a native `transition` as a MemoElement.
|
|
644
|
+
*
|
|
645
|
+
* MEMO models a transition as `part def Transition` with `sourceState` and
|
|
646
|
+
* `targetState` as **Strings** (§13.3) — and in the shipped content those
|
|
647
|
+
* strings hold display names ("Idle"), not element ids, so nothing can follow
|
|
648
|
+
* them to the states they name. The native form's source and target are real
|
|
649
|
+
* references, so they are resolved to element ids here.
|
|
650
|
+
*
|
|
651
|
+
* Both are still written into the attribute map under the same keys the part
|
|
652
|
+
* def declares. That is deliberate: it keeps every existing consumer of
|
|
653
|
+
* `sourceState` / `targetState` working while the two spellings coexist, and it
|
|
654
|
+
* is what makes the eventual migration a change of value (display name →
|
|
655
|
+
* element id) that a diff can show, rather than a change of shape that it
|
|
656
|
+
* cannot.
|
|
657
|
+
*
|
|
658
|
+
* An anonymous transition (`transition initial then off;`) declares no element.
|
|
659
|
+
* It is a control statement, not a named thing the model traces to.
|
|
660
|
+
*/
|
|
661
|
+
function extractTransition(transition, filePath, packageName, config, elements, registry, registries) {
|
|
662
|
+
if (!transition.name)
|
|
663
|
+
return;
|
|
664
|
+
const attributes = {
|
|
665
|
+
...extractAttributes(transition.body),
|
|
666
|
+
sourceState: transition.source,
|
|
667
|
+
targetState: transition.target,
|
|
668
|
+
};
|
|
669
|
+
if (transition.trigger)
|
|
670
|
+
attributes.trigger = transition.trigger;
|
|
671
|
+
if (transition.effect)
|
|
672
|
+
attributes.effectSummary = transition.effect;
|
|
673
|
+
const guard = renderGuardExpression(transition.guard);
|
|
674
|
+
if (guard !== undefined)
|
|
675
|
+
attributes.guardSummary = guard;
|
|
676
|
+
const { kindDef, resolvedKind } = transition.type
|
|
677
|
+
? resolveKindDef(transition.type, config, registries)
|
|
678
|
+
: { kindDef: undefined, resolvedKind: 'Unknown' };
|
|
679
|
+
elements.set(transition.name, {
|
|
680
|
+
id: transition.name,
|
|
681
|
+
name: attributes.name || transition.name,
|
|
682
|
+
kind: resolvedKind,
|
|
683
|
+
construct: 'transition',
|
|
684
|
+
layer: kindDef?.layer || 'unknown',
|
|
685
|
+
file: filePath,
|
|
686
|
+
package: packageName || undefined,
|
|
687
|
+
attributes,
|
|
688
|
+
doc: extractDocComment(transition.body),
|
|
689
|
+
});
|
|
690
|
+
registry.registerElement(transition.name, packageName);
|
|
354
691
|
}
|
|
355
692
|
/**
|
|
356
693
|
* Extract an ActionDefinition as a MemoElement with parameters.
|
|
357
694
|
*/
|
|
358
|
-
function extractActionDefinition(actionDef, filePath, packageName, config, elements, registry) {
|
|
695
|
+
function extractActionDefinition(actionDef, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries) {
|
|
359
696
|
const id = actionDef.name;
|
|
360
697
|
// Extract parameters from body
|
|
361
698
|
const parameters = [];
|
|
362
699
|
const bodyMembers = actionDef.body || [];
|
|
363
700
|
for (const member of bodyMembers) {
|
|
364
|
-
if (member.$type === 'ActionParameterMember') {
|
|
701
|
+
if (member.$type === 'ActionParameterMember' || (member.$type === 'ItemUsage' && member.direction)) {
|
|
365
702
|
const param = member;
|
|
366
703
|
parameters.push({
|
|
367
704
|
name: param.name,
|
|
368
705
|
direction: param.direction,
|
|
369
|
-
type: param.type,
|
|
706
|
+
type: param.type || 'Item',
|
|
370
707
|
});
|
|
371
708
|
}
|
|
372
709
|
}
|
|
@@ -388,6 +725,66 @@ function extractActionDefinition(actionDef, filePath, packageName, config, eleme
|
|
|
388
725
|
};
|
|
389
726
|
elements.set(id, element);
|
|
390
727
|
registry.registerElement(id, packageName);
|
|
728
|
+
// Standard SysML activity bodies may contain action/control usages directly
|
|
729
|
+
// (not wrapped in an ActionUsage). Preserve those declarations so a valid
|
|
730
|
+
// activity diagram cannot collapse to its enclosing action alone.
|
|
731
|
+
// `previousStep` carries the member a `then` refers back to: in standard
|
|
732
|
+
// SysML a body member written `then action x ...` succeeds the step declared
|
|
733
|
+
// before it, with no `succession` usage naming either end.
|
|
734
|
+
let previousStep;
|
|
735
|
+
let terminateCount = 0;
|
|
736
|
+
for (const member of bodyMembers) {
|
|
737
|
+
let step;
|
|
738
|
+
if (member.$type === 'ActionUsage') {
|
|
739
|
+
extractActionUsage(member, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries, id);
|
|
740
|
+
step = member.name;
|
|
741
|
+
}
|
|
742
|
+
else if (member.$type === 'ControlNodeUsage') {
|
|
743
|
+
extractControlNode(member, filePath, packageName, elements, registry, id);
|
|
744
|
+
step = member.name;
|
|
745
|
+
}
|
|
746
|
+
else if (['AcceptActionUsage', 'SendActionUsage', 'DecisionNodeUsage', 'MergeNodeUsage', 'TerminateUsage'].includes(member.$type)) {
|
|
747
|
+
const node = member;
|
|
748
|
+
// A terminate node has no name to be given one by, and an id keyed
|
|
749
|
+
// on `elements.size` moves whenever anything else in the file does.
|
|
750
|
+
// Key it on the action that owns it instead, so a view can name it
|
|
751
|
+
// and a saved layout keeps pointing at the same node.
|
|
752
|
+
const fallback = node.$type === 'TerminateUsage'
|
|
753
|
+
? `${id}__terminate${terminateCount++ === 0 ? '' : terminateCount}`
|
|
754
|
+
: `${node.$type}-${elements.size}`;
|
|
755
|
+
const nodeId = node.name ?? fallback;
|
|
756
|
+
step = nodeId;
|
|
757
|
+
extractStandardActivityNode(node, filePath, packageName, elements, registry, id, nodeId);
|
|
758
|
+
}
|
|
759
|
+
else if (member.$type === 'SuccessionUsage') {
|
|
760
|
+
deferredSuccessions.push({ succession: member, filePath, packageName, parentActionId: id });
|
|
761
|
+
}
|
|
762
|
+
if (step && member.followsPrevious && previousStep) {
|
|
763
|
+
deferredSuccessions.push({
|
|
764
|
+
succession: { steps: [{ ref: previousStep }, { ref: step }] },
|
|
765
|
+
filePath,
|
|
766
|
+
packageName,
|
|
767
|
+
parentActionId: id,
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
if (step)
|
|
771
|
+
previousStep = step;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
function extractStandardActivityNode(node, filePath, packageName, elements, registry, parentActionId, id) {
|
|
775
|
+
const typeToKind = {
|
|
776
|
+
AcceptActionUsage: 'AcceptActionUsage', SendActionUsage: 'SendActionUsage',
|
|
777
|
+
DecisionNodeUsage: 'DecisionNodeUsage', MergeNodeUsage: 'MergeNodeUsage', TerminateUsage: 'ActivityFinalNodeUsage',
|
|
778
|
+
};
|
|
779
|
+
const parameters = node.$type === 'AcceptActionUsage' && node.payloadName
|
|
780
|
+
? [{ name: node.payloadName, direction: 'out', type: node.payloadType ?? 'Item' }]
|
|
781
|
+
: undefined;
|
|
782
|
+
elements.set(id, {
|
|
783
|
+
id, name: node.name ?? node.$type, kind: typeToKind[node.$type] ?? node.$type,
|
|
784
|
+
construct: 'action', layer: 'behavior', file: filePath, package: packageName || undefined,
|
|
785
|
+
attributes: { ...(node.payloadName ? { payloadName: node.payloadName } : {}), ...(node.payloadType ? { payloadType: node.payloadType } : {}) }, parentAction: parentActionId, parameters,
|
|
786
|
+
});
|
|
787
|
+
registry.registerElement(id, packageName);
|
|
391
788
|
}
|
|
392
789
|
/**
|
|
393
790
|
* Extract an ItemDefinition as a MemoElement.
|
|
@@ -415,8 +812,19 @@ function extractItemDefinition(itemDef, filePath, packageName, config, elements,
|
|
|
415
812
|
registry.registerElement(id, packageName);
|
|
416
813
|
}
|
|
417
814
|
/**
|
|
418
|
-
* Walk
|
|
419
|
-
* Sets owner on ports and ownedPorts on the
|
|
815
|
+
* Walk an owner's body to extract port usages as owned port elements.
|
|
816
|
+
* Sets owner on ports and ownedPorts on the owner.
|
|
817
|
+
*
|
|
818
|
+
* The owner may be a definition (`part def Board { port p : DataPort; }`) or a
|
|
819
|
+
* USAGE — including another port. SysML v2 nests ports inside ports, which is
|
|
820
|
+
* how a panel cluster says "this one boundary feature carries these three
|
|
821
|
+
* connectors". Without the usage case a model that nests natively simply loses
|
|
822
|
+
* the children: they are declared, they resolve, and they never become
|
|
823
|
+
* elements, so they vanish from every diagram and every count. The only
|
|
824
|
+
* alternative spelling is a `Composes` connection from a port to a port, which
|
|
825
|
+
* CR-ONT-065 forbids — a whole in a decomposition has to be a part, an action
|
|
826
|
+
* or a state. So the native form was the only correct one, and it was the one
|
|
827
|
+
* that did not work.
|
|
420
828
|
*/
|
|
421
829
|
function extractDefinitionPorts(def, filePath, packageName, config, elements, registry, registries) {
|
|
422
830
|
const ownerId = def.name;
|
|
@@ -440,6 +848,37 @@ function extractDefinitionPorts(def, filePath, packageName, config, elements, re
|
|
|
440
848
|
}
|
|
441
849
|
}
|
|
442
850
|
}
|
|
851
|
+
/**
|
|
852
|
+
* Walk a part usage's body to extract nested parts as owned elements, setting
|
|
853
|
+
* `owner` on each child.
|
|
854
|
+
*
|
|
855
|
+
* `extractUsage` flattens the `PartMember` shapes that are view metadata — a
|
|
856
|
+
* reference binding (`part viewpoint :> vp;`) and an untyped body
|
|
857
|
+
* (`part :>> selectionQuery { ... }`). A TYPED nested part
|
|
858
|
+
* (`part valve : Valve { ... }`) is real containment: without this it is
|
|
859
|
+
* declared, resolves, and never becomes an element — the same silent drop
|
|
860
|
+
* nested ports had before `extractDefinitionPorts` walked port usages. The
|
|
861
|
+
* `composes` edge that makes containment legible to consumers is synthesized
|
|
862
|
+
* from the `owner` chain in buildMemoModel.
|
|
863
|
+
*/
|
|
864
|
+
function extractNestedParts(owner, filePath, packageName, config, elements, registry, registries) {
|
|
865
|
+
const ownerId = owner.name;
|
|
866
|
+
for (const member of owner.body || []) {
|
|
867
|
+
if (member.$type !== 'PartMember')
|
|
868
|
+
continue;
|
|
869
|
+
const pm = member;
|
|
870
|
+
// Only a TYPED nested part is containment. Untyped bodies (view
|
|
871
|
+
// selectionQuery) and reference bindings are view metadata, flattened
|
|
872
|
+
// to attributes in extractUsage — skip them here or a view's metadata
|
|
873
|
+
// becomes a phantom element and its selection query is lost.
|
|
874
|
+
if (!pm.type || pm.boundRef || !pm.name)
|
|
875
|
+
continue;
|
|
876
|
+
extractUsage({ name: pm.name, type: pm.type, body: pm.body }, 'part', filePath, packageName, config, elements, registry, registries);
|
|
877
|
+
const childEl = elements.get(pm.name);
|
|
878
|
+
if (childEl)
|
|
879
|
+
childEl.owner = ownerId;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
443
882
|
/**
|
|
444
883
|
* Extract an ActionUsage, including nested actions, flows, and successions.
|
|
445
884
|
* Supports both typed (action name : Type;) and composite (action name { ... }) forms.
|
|
@@ -482,6 +921,9 @@ function extractActionUsage(usage, filePath, packageName, config, elements, defe
|
|
|
482
921
|
attributes,
|
|
483
922
|
doc,
|
|
484
923
|
parentAction: parentActionId,
|
|
924
|
+
parameters: bodyMembers
|
|
925
|
+
.filter(member => member.$type === 'ActionParameterMember')
|
|
926
|
+
.map(member => ({ name: member.name, direction: member.direction, type: member.type || 'Item' })),
|
|
485
927
|
};
|
|
486
928
|
elements.set(id, element);
|
|
487
929
|
registry.registerElement(id, packageName);
|
|
@@ -515,18 +957,22 @@ function extractActionUsage(usage, filePath, packageName, config, elements, defe
|
|
|
515
957
|
}
|
|
516
958
|
}
|
|
517
959
|
/**
|
|
518
|
-
* Extract a
|
|
960
|
+
* Extract a control node. Modeled as a behavior-layer element with
|
|
519
961
|
* `construct: 'action'` so it participates in succession ordering and swimlane
|
|
520
|
-
* layout like any other flow step, but carries
|
|
521
|
-
*
|
|
522
|
-
*
|
|
962
|
+
* layout like any other flow step, but carries the metaclass its `controlKind`
|
|
963
|
+
* names and a `controlKind` attribute, so renderers draw the right symbol —
|
|
964
|
+
* a bar for fork/join, a diamond for decide/merge.
|
|
965
|
+
*
|
|
966
|
+
* The kind comes from `CONTROL_KIND_METACLASS`, the same binding
|
|
967
|
+
* `activityNodeType` classifies by; a second mapping here is how `decide` and
|
|
968
|
+
* `merge` came to be stored as `JoinNode`.
|
|
523
969
|
*/
|
|
524
970
|
function extractControlNode(node, filePath, packageName, elements, registry, parentActionId) {
|
|
525
971
|
const id = node.name;
|
|
526
|
-
const kind = node.controlKind
|
|
972
|
+
const kind = CONTROL_KIND_METACLASS[node.controlKind];
|
|
527
973
|
elements.set(id, {
|
|
528
974
|
id,
|
|
529
|
-
name: node.
|
|
975
|
+
name: node.name,
|
|
530
976
|
kind,
|
|
531
977
|
construct: 'action',
|
|
532
978
|
layer: 'behavior',
|
|
@@ -539,12 +985,15 @@ function extractControlNode(node, filePath, packageName, elements, registry, par
|
|
|
539
985
|
}
|
|
540
986
|
function resolveConnection(conn, filePath, packageName, config, elements, relationships, registry, allElementIds) {
|
|
541
987
|
const typeName = conn.type; // e.g. "Mitigates", "TraceTo"
|
|
542
|
-
if (!typeName)
|
|
543
|
-
return;
|
|
544
988
|
if (!conn.source || !conn.target)
|
|
545
989
|
return;
|
|
546
|
-
//
|
|
547
|
-
|
|
990
|
+
// An untyped connection (`connection connect a to b;`, no `: SomeDef`) is
|
|
991
|
+
// the native binary connection with nothing further classifying it — the
|
|
992
|
+
// keyword IS the type, `connect`, the same as `flow`/`bind` (R10-S6,
|
|
993
|
+
// `ConnectsPhysically`'s migration). Before this it built to nothing at
|
|
994
|
+
// all: the same silent-drop shape as `BindingUsage`/`ExposeMember`.
|
|
995
|
+
// A typed connection normalizes its definition name: "Mitigates" → "mitigates".
|
|
996
|
+
const normalizedType = typeName ? normalizeRelType(typeName) : 'connect';
|
|
548
997
|
// Resolve source and target using registry for cross-file resolution
|
|
549
998
|
const sourceId = resolveEndpointId(conn.source.ref, packageName, registry, allElementIds);
|
|
550
999
|
const targetId = resolveEndpointId(conn.target.ref, packageName, registry, allElementIds);
|
|
@@ -552,7 +1001,7 @@ function resolveConnection(conn, filePath, packageName, config, elements, relati
|
|
|
552
1001
|
return;
|
|
553
1002
|
// A named connection usage carries its own stable ID; anonymous ones fall
|
|
554
1003
|
// back to a positional counter that shifts whenever the file changes.
|
|
555
|
-
const attributes = extractAttributes(conn.body);
|
|
1004
|
+
const attributes = { ...extractAttributes(conn.body), ...extractRelationshipMetadata(conn.body) };
|
|
556
1005
|
const rel = {
|
|
557
1006
|
id: conn.name || `rel-${++relationshipCounter}`,
|
|
558
1007
|
type: normalizedType,
|
|
@@ -561,6 +1010,9 @@ function resolveConnection(conn, filePath, packageName, config, elements, relati
|
|
|
561
1010
|
targetId,
|
|
562
1011
|
targetEnd: conn.target.endName,
|
|
563
1012
|
file: filePath,
|
|
1013
|
+
sourceRange: conn.$cstNode
|
|
1014
|
+
? { offset: conn.$cstNode.offset, length: conn.$cstNode.length }
|
|
1015
|
+
: undefined,
|
|
564
1016
|
named: conn.name ? true : undefined,
|
|
565
1017
|
attributes,
|
|
566
1018
|
flowItem: attributes.transportedItem || attributes.flowItem || undefined,
|
|
@@ -576,33 +1028,97 @@ function resolveConnection(conn, filePath, packageName, config, elements, relati
|
|
|
576
1028
|
}
|
|
577
1029
|
relationships.push(rel);
|
|
578
1030
|
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Resolve a dotted endpoint path to the deepest element it names.
|
|
1033
|
+
*
|
|
1034
|
+
* A dotted endpoint has two shapes and they resolve differently.
|
|
1035
|
+
*
|
|
1036
|
+
* `receive.prescription` names an action and one of its PARAMETERS. The
|
|
1037
|
+
* parameter is not an element, so the endpoint is the action and the parameter
|
|
1038
|
+
* is the end label.
|
|
1039
|
+
*
|
|
1040
|
+
* `touchscreen.touchUsbIo` names a port and a port NESTED inside it, and
|
|
1041
|
+
* `coffeeMachine.serviceInterface.diagnostics` nests one level deeper again.
|
|
1042
|
+
* The nested port IS an element in its own right, so the endpoint is the child.
|
|
1043
|
+
* Reading it the first way silently retargets the edge at the parent, which is
|
|
1044
|
+
* not a resolution failure anyone sees: it produces a plausible relationship
|
|
1045
|
+
* pointing at the wrong feature, and it only surfaces later as a payload
|
|
1046
|
+
* mismatch on whichever edge happened to carry a different item from its
|
|
1047
|
+
* parent's.
|
|
1048
|
+
*
|
|
1049
|
+
* Walk the path through `owner` and take the deepest real element.
|
|
1050
|
+
*/
|
|
1051
|
+
function resolveEndpoint(ref, elements) {
|
|
1052
|
+
const parts = ref.split('.');
|
|
1053
|
+
let id = parts[0];
|
|
1054
|
+
let i = 1;
|
|
1055
|
+
while (i < parts.length) {
|
|
1056
|
+
const child = elements.get(parts[i]);
|
|
1057
|
+
if (!child || child.owner !== id)
|
|
1058
|
+
break;
|
|
1059
|
+
id = parts[i];
|
|
1060
|
+
i++;
|
|
1061
|
+
}
|
|
1062
|
+
return { id, end: parts.slice(i).join('.') };
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Resolve a `bind outer = inner;` port delegation into a MemoRelationship.
|
|
1066
|
+
*
|
|
1067
|
+
* Unlike a flow this carries no item: delegation is identity, so there is
|
|
1068
|
+
* nothing travelling and nothing to label the edge with. Consumers that render
|
|
1069
|
+
* an itemless edge already suppress the label.
|
|
1070
|
+
*/
|
|
1071
|
+
function resolveBinding(binding, filePath, _packageName, relationships, allElementIds, elements) {
|
|
1072
|
+
const sourceRef = binding.source;
|
|
1073
|
+
const targetRef = binding.target;
|
|
1074
|
+
if (!sourceRef || !targetRef)
|
|
1075
|
+
return;
|
|
1076
|
+
const { id: sourceId, end: sourceEnd } = resolveEndpoint(sourceRef, elements);
|
|
1077
|
+
const { id: targetId, end: targetEnd } = resolveEndpoint(targetRef, elements);
|
|
1078
|
+
if (!allElementIds.has(sourceId) || !allElementIds.has(targetId))
|
|
1079
|
+
return;
|
|
1080
|
+
relationships.push({
|
|
1081
|
+
id: `rel-${++relationshipCounter}`,
|
|
1082
|
+
type: 'bind',
|
|
1083
|
+
sourceId,
|
|
1084
|
+
sourceEnd,
|
|
1085
|
+
targetId,
|
|
1086
|
+
targetEnd,
|
|
1087
|
+
file: filePath,
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
579
1090
|
/**
|
|
580
1091
|
* Resolve a flow connection usage into a MemoRelationship.
|
|
581
1092
|
* Flow endpoints use dot notation: "actionName.paramName"
|
|
582
1093
|
*/
|
|
583
|
-
function resolveFlowConnection(flow, filePath, packageName, parentActionId, relationships, allElementIds) {
|
|
1094
|
+
function resolveFlowConnection(flow, filePath, packageName, parentActionId, relationships, allElementIds, elements) {
|
|
584
1095
|
const sourceRef = flow.source?.ref;
|
|
585
1096
|
const targetRef = flow.target?.ref;
|
|
586
1097
|
if (!sourceRef || !targetRef)
|
|
587
1098
|
return;
|
|
588
|
-
|
|
589
|
-
const
|
|
590
|
-
const targetParts = targetRef.split('.');
|
|
591
|
-
const sourceActionId = sourceParts[0];
|
|
592
|
-
const sourcePort = sourceParts.length > 1 ? sourceParts.slice(1).join('.') : '';
|
|
593
|
-
const targetActionId = targetParts[0];
|
|
594
|
-
const targetPort = targetParts.length > 1 ? targetParts.slice(1).join('.') : '';
|
|
1099
|
+
const { id: sourceActionId, end: sourcePort } = resolveEndpoint(sourceRef, elements);
|
|
1100
|
+
const { id: targetActionId, end: targetPort } = resolveEndpoint(targetRef, elements);
|
|
595
1101
|
// Only create relationship if both endpoints reference known elements
|
|
596
1102
|
if (!allElementIds.has(sourceActionId) || !allElementIds.has(targetActionId))
|
|
597
1103
|
return;
|
|
1104
|
+
// A NAMED flow carries a stable ID that survives rebuilds; an anonymous one
|
|
1105
|
+
// falls back to a positional counter that shifts whenever the file changes.
|
|
1106
|
+
// Same rule `resolveConnection` applies to connection usages, and the same
|
|
1107
|
+
// reason: authoring needs to inspect, delete, and deep-link a flow, and a
|
|
1108
|
+
// positional id makes every one of those wrong after the next edit.
|
|
598
1109
|
const rel = {
|
|
599
|
-
id: `rel-${++relationshipCounter}`,
|
|
1110
|
+
id: flow.name || `rel-${++relationshipCounter}`,
|
|
600
1111
|
type: 'flow',
|
|
601
1112
|
sourceId: sourceActionId,
|
|
602
1113
|
sourceEnd: sourcePort,
|
|
603
1114
|
targetId: targetActionId,
|
|
604
1115
|
targetEnd: targetPort,
|
|
605
1116
|
file: filePath,
|
|
1117
|
+
sourceRange: flow.$cstNode
|
|
1118
|
+
? { offset: flow.$cstNode.offset, length: flow.$cstNode.length }
|
|
1119
|
+
: undefined,
|
|
1120
|
+
named: flow.name ? true : undefined,
|
|
1121
|
+
attributes: extractAttributes(flow.body),
|
|
606
1122
|
flowItem: flow.itemType || undefined,
|
|
607
1123
|
};
|
|
608
1124
|
relationships.push(rel);
|
|
@@ -630,11 +1146,12 @@ function resolveSuccession(succession, filePath, packageName, parentActionId, re
|
|
|
630
1146
|
const targetKnown = toRef === 'done' || allElementIds.has(targetId);
|
|
631
1147
|
if (!sourceKnown || !targetKnown)
|
|
632
1148
|
continue;
|
|
1149
|
+
const guardLabel = renderGuardExpression(steps[i].guard);
|
|
633
1150
|
const rel = {
|
|
634
1151
|
id: `rel-${++relationshipCounter}`,
|
|
635
1152
|
type: 'succession',
|
|
636
1153
|
sourceId,
|
|
637
|
-
sourceEnd: ''
|
|
1154
|
+
sourceEnd: guardLabel === undefined ? '' : `[${guardLabel}]`,
|
|
638
1155
|
targetId,
|
|
639
1156
|
targetEnd: '',
|
|
640
1157
|
file: filePath,
|
|
@@ -642,10 +1159,48 @@ function resolveSuccession(succession, filePath, packageName, parentActionId, re
|
|
|
642
1159
|
relationships.push(rel);
|
|
643
1160
|
}
|
|
644
1161
|
}
|
|
1162
|
+
/**
|
|
1163
|
+
* Preserve a SysML succession guard as readable diagram text.
|
|
1164
|
+
*
|
|
1165
|
+
* Guards use the same expression AST as constraints. Previously only literal
|
|
1166
|
+
* `true`/`false` nodes happened to carry one of the three fields inspected by
|
|
1167
|
+
* the builder, so a valid guard such as `validUser == true` silently vanished
|
|
1168
|
+
* during lowering even though SysIDE accepted it.
|
|
1169
|
+
*/
|
|
1170
|
+
function renderGuardExpression(expr) {
|
|
1171
|
+
if (!expr)
|
|
1172
|
+
return undefined;
|
|
1173
|
+
switch (expr.$type) {
|
|
1174
|
+
case 'LiteralExpr':
|
|
1175
|
+
return expr.boolValue ?? expr.intValue ?? expr.strValue;
|
|
1176
|
+
case 'FeatureChain':
|
|
1177
|
+
return Array.isArray(expr.segments) ? expr.segments.join('.') : undefined;
|
|
1178
|
+
case 'UnaryExpr': {
|
|
1179
|
+
const operand = renderGuardExpression(expr.operand);
|
|
1180
|
+
return operand === undefined ? undefined : `${expr.op} ${operand}`;
|
|
1181
|
+
}
|
|
1182
|
+
case 'BinaryExpr': {
|
|
1183
|
+
const left = renderGuardExpression(expr.left);
|
|
1184
|
+
const right = renderGuardExpression(expr.right);
|
|
1185
|
+
return left === undefined || right === undefined
|
|
1186
|
+
? undefined
|
|
1187
|
+
: `${left} ${expr.op} ${right}`;
|
|
1188
|
+
}
|
|
1189
|
+
case 'CollectionOp': {
|
|
1190
|
+
const target = renderGuardExpression(expr.target);
|
|
1191
|
+
const argument = renderGuardExpression(expr.argument);
|
|
1192
|
+
if (target === undefined)
|
|
1193
|
+
return undefined;
|
|
1194
|
+
return `${target}->${expr.op}(${argument ?? ''})`;
|
|
1195
|
+
}
|
|
1196
|
+
default:
|
|
1197
|
+
return expr.text ?? expr.value;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
645
1200
|
/**
|
|
646
1201
|
* Resolve an allocate usage into a MemoRelationship and set allocatedTo on the element.
|
|
647
1202
|
*/
|
|
648
|
-
function resolveAllocate(allocate, filePath, packageName, elements, relationships, registry, allElementIds) {
|
|
1203
|
+
function resolveAllocate(allocate, filePath, packageName, elements, relationships, registry, allElementIds, relationshipRegistry) {
|
|
649
1204
|
const sourceRef = allocate.source;
|
|
650
1205
|
const targetRef = allocate.target;
|
|
651
1206
|
if (!sourceRef || !targetRef)
|
|
@@ -660,16 +1215,310 @@ function resolveAllocate(allocate, filePath, packageName, elements, relationship
|
|
|
660
1215
|
if (sourceEl) {
|
|
661
1216
|
sourceEl.allocatedTo = targetId;
|
|
662
1217
|
}
|
|
663
|
-
|
|
1218
|
+
// `allocate a to b;` and `connection : AllocatedTo connect …` are the same
|
|
1219
|
+
// statement, so they produce the same edge. They did not: the native form
|
|
1220
|
+
// emitted `allocateTo` with invented ends while the connection emitted
|
|
1221
|
+
// `allocatedTo` with the ontology's, and consumers keyed on one silently
|
|
1222
|
+
// missed the other — the DHF allocation queries ask for `allocatedTo`.
|
|
1223
|
+
//
|
|
1224
|
+
// A TYPED allocation — `allocation d : DeploysTo allocate m to node;` —
|
|
1225
|
+
// carries which allocation it is, and that distinction has to survive.
|
|
1226
|
+
// `DeploysTo` and `BuildsInto` are not `AllocatedTo` under another name:
|
|
1227
|
+
// they are separate edges the deployment views and the DHF read by name.
|
|
1228
|
+
// The `allocation def` naming them is what the typed form points at, so the
|
|
1229
|
+
// edge is its camelCase name whenever the registry knows it; an unknown or
|
|
1230
|
+
// absent type falls back to the base allocation, which is what bare
|
|
1231
|
+
// `allocate` has always meant.
|
|
1232
|
+
const typed = allocate.type ? pascalToCamelCase(allocate.type.split('::').pop()) : undefined;
|
|
1233
|
+
const edge = typed && relationshipRegistry?.has(typed) ? typed : 'allocatedTo';
|
|
1234
|
+
relationships.push(edge === 'allocatedTo'
|
|
1235
|
+
? nativeTraceEdge('allocatedTo', sourceId, targetId, filePath)
|
|
1236
|
+
: typedAllocationEdge(edge, sourceId, targetId, filePath, relationshipRegistry));
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* The trace edge for an `allocation x : SomeAllocationDef allocate a to b;`.
|
|
1240
|
+
*
|
|
1241
|
+
* Ends come from the registry entry for the named definition, so a typed
|
|
1242
|
+
* allocation and the equivalent `connection : SomeAllocationDef connect …`
|
|
1243
|
+
* produce byte-identical links — the same guarantee the three
|
|
1244
|
+
* LANGUAGE_NATIVE_RELATIONS rows carry, extended to every allocation def the
|
|
1245
|
+
* ontology declares rather than to a fixed list of three.
|
|
1246
|
+
*/
|
|
1247
|
+
function typedAllocationEdge(type, sourceId, targetId, filePath, relationshipRegistry) {
|
|
1248
|
+
const ends = relationshipRegistry?.getRelType(type)?.ends ?? [];
|
|
1249
|
+
return {
|
|
664
1250
|
id: `rel-${++relationshipCounter}`,
|
|
665
|
-
type
|
|
1251
|
+
type,
|
|
666
1252
|
sourceId,
|
|
667
|
-
sourceEnd: '
|
|
1253
|
+
sourceEnd: ends[0]?.name ?? 'source',
|
|
668
1254
|
targetId,
|
|
669
|
-
targetEnd: '
|
|
1255
|
+
targetEnd: ends[1]?.name ?? 'target',
|
|
1256
|
+
file: filePath,
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
/** Build the trace edge for a language-native relation, typed from the registry. */
|
|
1260
|
+
function nativeTraceEdge(name, sourceId, targetId, filePath) {
|
|
1261
|
+
const [sourceEnd, targetEnd] = LANGUAGE_NATIVE_RELATIONS[name].ends;
|
|
1262
|
+
return {
|
|
1263
|
+
id: `rel-${++relationshipCounter}`,
|
|
1264
|
+
type: name,
|
|
1265
|
+
sourceId,
|
|
1266
|
+
sourceEnd: sourceEnd.name,
|
|
1267
|
+
targetId,
|
|
1268
|
+
targetEnd: targetEnd.name,
|
|
670
1269
|
file: filePath,
|
|
671
1270
|
};
|
|
672
|
-
|
|
1271
|
+
}
|
|
1272
|
+
/**
|
|
1273
|
+
* The owner context of a native trace usage: the package it is declared in, and
|
|
1274
|
+
* the nearest enclosing named element.
|
|
1275
|
+
*
|
|
1276
|
+
* `verify` needs the second one — the case that does the verifying is the owner
|
|
1277
|
+
* of the member, never a written end — and `satisfy` needs the first to resolve
|
|
1278
|
+
* its references the way every other endpoint is resolved.
|
|
1279
|
+
*/
|
|
1280
|
+
function nativeUsageContext(node) {
|
|
1281
|
+
const packages = [];
|
|
1282
|
+
let ownerId;
|
|
1283
|
+
for (let current = node.$container; current; current = current.$container) {
|
|
1284
|
+
if (current.$type === 'PackageDeclaration') {
|
|
1285
|
+
if (current.name)
|
|
1286
|
+
packages.unshift(current.name);
|
|
1287
|
+
continue;
|
|
1288
|
+
}
|
|
1289
|
+
// An `objective` is a MEMBERSHIP, not the element that does the
|
|
1290
|
+
// verifying — the standard writes `objective { verify r; }` inside the
|
|
1291
|
+
// case, and the case is the verifier. A named objective would otherwise
|
|
1292
|
+
// capture `ownerId` and the `verifiedBy` edge would point at a wrapper
|
|
1293
|
+
// that is not an extracted element, silently dropping the link.
|
|
1294
|
+
if (current.$type === 'ObjectiveMember')
|
|
1295
|
+
continue;
|
|
1296
|
+
if (ownerId === undefined && typeof current.name === 'string' && current.name) {
|
|
1297
|
+
ownerId = current.name;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return { packageName: packages.join('::'), ownerId };
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Project a native usage that names ONE end and takes the other from its owner.
|
|
1304
|
+
*
|
|
1305
|
+
* `perform`, `include`, `exhibit` and `frame` all have this shape, and it is
|
|
1306
|
+
* `verify`'s shape with the ends swapped: `verify` names its source and owns
|
|
1307
|
+
* its target, these four own their source and name their target. Sharing the
|
|
1308
|
+
* resolution keeps the four from drifting apart, and keeps the rule that the
|
|
1309
|
+
* owner supplies the unwritten end stated in exactly one place.
|
|
1310
|
+
*/
|
|
1311
|
+
function resolveOwnerRootedUsage(node, written, name, filePath, relationships, registry, allElementIds) {
|
|
1312
|
+
if (!written)
|
|
1313
|
+
return;
|
|
1314
|
+
const { packageName, ownerId } = nativeUsageContext(node);
|
|
1315
|
+
const sourceId = ownerId
|
|
1316
|
+
? resolveEndpointId(ownerId, packageName, registry, allElementIds)
|
|
1317
|
+
: undefined;
|
|
1318
|
+
const targetId = resolveEndpointId(written, packageName, registry, allElementIds);
|
|
1319
|
+
if (!sourceId || !targetId)
|
|
1320
|
+
return;
|
|
1321
|
+
relationships.push(nativeTraceEdge(name, sourceId, targetId, filePath));
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Project a verification case's `subject` onto the `verifiedBy` edge.
|
|
1325
|
+
*
|
|
1326
|
+
* This is the standard's answer to verifying something that is not a
|
|
1327
|
+
* requirement: the verified element becomes the case's SUBJECT and the
|
|
1328
|
+
* requirement its `objective { verify … }`. 61 of MEMO's 99 `VerifiedBy` links
|
|
1329
|
+
* target a SystemFunction, a RiskControlMeasure, a SoftwareModule, a
|
|
1330
|
+
* BehaviorProperty or a TimingConstraint — none of which native `verify`
|
|
1331
|
+
* admits, because `verify` takes a RequirementUsage.
|
|
1332
|
+
*
|
|
1333
|
+
* The edge direction matches `VerifiedBy`: the subject is the source
|
|
1334
|
+
* (verificationTarget) and the owning case the target (verificationCase).
|
|
1335
|
+
*
|
|
1336
|
+
* A `subject` that declares a fresh feature rather than pointing at an existing
|
|
1337
|
+
* element — `subject testVehicle : Vehicle;` — binds nothing and contributes no
|
|
1338
|
+
* edge. Only the referring forms (`subject v :> vehicleTestConfig;`,
|
|
1339
|
+
* `subject v = vehicleTestConfig;`) name something already in the model. A
|
|
1340
|
+
* multi-valued subject is one parameter whose binding is a parenthesized list;
|
|
1341
|
+
* each bound element is one `verifiedBy` fact for the owning case.
|
|
1342
|
+
*/
|
|
1343
|
+
function resolveSubject(subject, filePath, relationships, registry, allElementIds) {
|
|
1344
|
+
if (!subject.boundRefs?.length)
|
|
1345
|
+
return;
|
|
1346
|
+
const { packageName, ownerId } = nativeUsageContext(subject);
|
|
1347
|
+
const targetId = ownerId
|
|
1348
|
+
? resolveEndpointId(ownerId, packageName, registry, allElementIds)
|
|
1349
|
+
: undefined;
|
|
1350
|
+
if (!targetId)
|
|
1351
|
+
return;
|
|
1352
|
+
for (const boundRef of subject.boundRefs) {
|
|
1353
|
+
const sourceId = resolveEndpointId(boundRef, packageName, registry, allElementIds);
|
|
1354
|
+
if (sourceId)
|
|
1355
|
+
relationships.push(nativeTraceEdge('verifiedBy', sourceId, targetId, filePath));
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Project a native `actor` onto the `participatesIn` edge (R10-S6).
|
|
1360
|
+
*
|
|
1361
|
+
* Same shape as `resolveSubject`: only the REFERRING form —
|
|
1362
|
+
* `actor driver = existingPart;` — names something already in the model, so
|
|
1363
|
+
* only that form produces an edge. A fresh declaration (`actor x : Person;`,
|
|
1364
|
+
* no `boundRef`) introduces a locally-scoped actor the model does not yet
|
|
1365
|
+
* have an element for; collapsing `MemoRelationship`'s `Initiates` and
|
|
1366
|
+
* `ParticipatesIn` onto the single native `actor` keyword means the
|
|
1367
|
+
* initiating/participating distinction is no longer a typed relationship —
|
|
1368
|
+
* it lives in how the actor is named, the same way `Composes` gave up its
|
|
1369
|
+
* whole/part distinction to plain nesting.
|
|
1370
|
+
*
|
|
1371
|
+
* The owner is the TARGET and the written reference the SOURCE — `verify`'s
|
|
1372
|
+
* shape, not `perform`'s: the use case is what the actor participates IN.
|
|
1373
|
+
*/
|
|
1374
|
+
function resolveActorParticipation(actor, filePath, relationships, registry, allElementIds) {
|
|
1375
|
+
if (!actor.boundRef)
|
|
1376
|
+
return;
|
|
1377
|
+
const { packageName, ownerId } = nativeUsageContext(actor);
|
|
1378
|
+
const sourceId = resolveEndpointId(actor.boundRef, packageName, registry, allElementIds);
|
|
1379
|
+
const targetId = ownerId ? resolveEndpointId(ownerId, packageName, registry, allElementIds) : undefined;
|
|
1380
|
+
if (!sourceId || !targetId)
|
|
1381
|
+
return;
|
|
1382
|
+
relationships.push(nativeTraceEdge('participatesIn', sourceId, targetId, filePath));
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Project every `dependency a to b;` onto the generic `dependency` edge, and
|
|
1386
|
+
* additionally onto `realizes` when it carries `#refinement` (R10-S6).
|
|
1387
|
+
*
|
|
1388
|
+
* The only native relation here that is not a connection. A Dependency takes n
|
|
1389
|
+
* clients and n suppliers rather than a source and a target, so one written
|
|
1390
|
+
* dependency can produce several edges — `dependency Schemata from s to a, b;`
|
|
1391
|
+
* is two statements sharing a name, and it lowers to two links, which is what
|
|
1392
|
+
* `Realizes` would have needed two connection usages to say.
|
|
1393
|
+
*
|
|
1394
|
+
* A dependency WITHOUT `#refinement` is an unclassified dependency: it means
|
|
1395
|
+
* strictly less than `Realizes` does, so it contributes only the generic
|
|
1396
|
+
* `dependency` edge, never `realizes` — inferring realization from a bare
|
|
1397
|
+
* dependency would put a claim in the traceability matrix that the model
|
|
1398
|
+
* never made. `#refinement` adds `realizes` on top; it does not replace the
|
|
1399
|
+
* generic edge, because a refinement dependency IS a dependency.
|
|
1400
|
+
*
|
|
1401
|
+
* Before R10-S6 a bare (non-`#refinement`) dependency built to nothing at
|
|
1402
|
+
* all — the same silent-drop shape as `BindingUsage`/`ExposeMember` — which
|
|
1403
|
+
* is what `ModuleUses`/`MonitorsChannel`'s migration to plain `dependency`
|
|
1404
|
+
* would otherwise have hit. Both collapse onto this one generic edge; native
|
|
1405
|
+
* `dependency` does not distinguish "uses a module" from "monitors a
|
|
1406
|
+
* channel" any more than `actor` distinguished an initiating actor from a
|
|
1407
|
+
* participating one, so that distinction now lives in the dependency's own
|
|
1408
|
+
* name/doc, not in a relationship type.
|
|
1409
|
+
*/
|
|
1410
|
+
function resolveDependency(dependency, filePath, relationships, registry, allElementIds) {
|
|
1411
|
+
const isRefinement = (dependency.prefixMetadata ?? [])
|
|
1412
|
+
.some(annotation => annotation.type?.split('::').pop() === REFINEMENT_METADATA);
|
|
1413
|
+
const { packageName } = nativeUsageContext(dependency);
|
|
1414
|
+
for (const client of dependency.clients ?? []) {
|
|
1415
|
+
const sourceId = resolveEndpointId(client, packageName, registry, allElementIds);
|
|
1416
|
+
if (!sourceId)
|
|
1417
|
+
continue;
|
|
1418
|
+
for (const supplier of dependency.suppliers ?? []) {
|
|
1419
|
+
const targetId = resolveEndpointId(supplier, packageName, registry, allElementIds);
|
|
1420
|
+
if (!targetId)
|
|
1421
|
+
continue;
|
|
1422
|
+
relationships.push(nativeTraceEdge('dependency', sourceId, targetId, filePath));
|
|
1423
|
+
if (isRefinement)
|
|
1424
|
+
relationships.push(nativeTraceEdge('realizes', sourceId, targetId, filePath));
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Project every `satisfy` and `verify` in a document onto the trace edge its
|
|
1430
|
+
* MEMO connection-def equivalent produces.
|
|
1431
|
+
*/
|
|
1432
|
+
function resolveNativeTraceUsages(model, filePath, relationships, registry, allElementIds) {
|
|
1433
|
+
for (const node of AstUtils.streamAllContents(model)) {
|
|
1434
|
+
if (isSatisfyRequirementUsage(node)) {
|
|
1435
|
+
resolveSatisfy(node, filePath, relationships, registry, allElementIds);
|
|
1436
|
+
}
|
|
1437
|
+
else if (isRequirementVerificationMember(node)) {
|
|
1438
|
+
resolveVerify(node, filePath, relationships, registry, allElementIds);
|
|
1439
|
+
}
|
|
1440
|
+
else if (isPerformActionUsage(node)) {
|
|
1441
|
+
resolveOwnerRootedUsage(node, node.performed, 'performs', filePath, relationships, registry, allElementIds);
|
|
1442
|
+
}
|
|
1443
|
+
else if (isIncludeUseCaseUsage(node)) {
|
|
1444
|
+
resolveOwnerRootedUsage(node, node.included, 'includesStep', filePath, relationships, registry, allElementIds);
|
|
1445
|
+
}
|
|
1446
|
+
else if (isExhibitStateUsage(node)) {
|
|
1447
|
+
resolveOwnerRootedUsage(node, node.exhibited, 'exhibitsMode', filePath, relationships, registry, allElementIds);
|
|
1448
|
+
}
|
|
1449
|
+
else if (isFramedConcernMember(node)) {
|
|
1450
|
+
resolveOwnerRootedUsage(node, node.framed, 'framesConcern', filePath, relationships, registry, allElementIds);
|
|
1451
|
+
}
|
|
1452
|
+
else if (isSubjectMember(node)) {
|
|
1453
|
+
resolveSubject(node, filePath, relationships, registry, allElementIds);
|
|
1454
|
+
}
|
|
1455
|
+
else if (isActorMember(node)) {
|
|
1456
|
+
resolveActorParticipation(node, filePath, relationships, registry, allElementIds);
|
|
1457
|
+
}
|
|
1458
|
+
else if (isDependency(node)) {
|
|
1459
|
+
resolveDependency(node, filePath, relationships, registry, allElementIds);
|
|
1460
|
+
}
|
|
1461
|
+
else if (isVariantMember(node)) {
|
|
1462
|
+
resolveVariant(node, filePath, relationships, registry, allElementIds);
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
/**
|
|
1467
|
+
* Project `variant x;` onto a navigable choice-point edge.
|
|
1468
|
+
*
|
|
1469
|
+
* A variation's alternatives are memberships rather than connection usages,
|
|
1470
|
+
* so they would otherwise disappear from the consumer model entirely. The
|
|
1471
|
+
* nearest owner is the variation point and the written member names the
|
|
1472
|
+
* selected configuration. Keeping this as a first-class edge lets DSMs and
|
|
1473
|
+
* views distinguish a real choice from four unrelated parts.
|
|
1474
|
+
*/
|
|
1475
|
+
function resolveVariant(variant, filePath, relationships, registry, allElementIds) {
|
|
1476
|
+
const { packageName, ownerId } = nativeUsageContext(variant);
|
|
1477
|
+
const sourceId = ownerId
|
|
1478
|
+
? resolveEndpointId(ownerId, packageName, registry, allElementIds)
|
|
1479
|
+
: undefined;
|
|
1480
|
+
const targetId = resolveEndpointId(variant.name, packageName, registry, allElementIds);
|
|
1481
|
+
if (!sourceId || !targetId)
|
|
1482
|
+
return;
|
|
1483
|
+
relationships.push({
|
|
1484
|
+
id: `rel-${++relationshipCounter}`,
|
|
1485
|
+
type: 'variant',
|
|
1486
|
+
sourceId,
|
|
1487
|
+
sourceEnd: 'variationPoint',
|
|
1488
|
+
targetId,
|
|
1489
|
+
targetEnd: 'variant',
|
|
1490
|
+
file: filePath,
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
function resolveSatisfy(satisfy, filePath, relationships, registry, allElementIds) {
|
|
1494
|
+
// A negated claim — `assert not satisfy r by p;` — states that the
|
|
1495
|
+
// requirement is NOT satisfied. There is no MEMO connection for it, and
|
|
1496
|
+
// emitting a `satisfiedBy` edge would make a design review's rejection read
|
|
1497
|
+
// as coverage in the traceability matrix. It parses; it contributes no
|
|
1498
|
+
// trace edge until the model has somewhere honest to put it.
|
|
1499
|
+
if (satisfy.isNegated)
|
|
1500
|
+
return;
|
|
1501
|
+
const { packageName } = nativeUsageContext(satisfy);
|
|
1502
|
+
const sourceId = resolveEndpointId(satisfy.requirement, packageName, registry, allElementIds);
|
|
1503
|
+
// Without `by`, the satisfying subject is inherited from the enclosing
|
|
1504
|
+
// requirement rather than written. Nothing to bind, so no edge.
|
|
1505
|
+
const targetId = satisfy.satisfyingFeature
|
|
1506
|
+
? resolveEndpointId(satisfy.satisfyingFeature, packageName, registry, allElementIds)
|
|
1507
|
+
: undefined;
|
|
1508
|
+
if (!sourceId || !targetId)
|
|
1509
|
+
return;
|
|
1510
|
+
relationships.push(nativeTraceEdge('satisfiedBy', sourceId, targetId, filePath));
|
|
1511
|
+
}
|
|
1512
|
+
function resolveVerify(verify, filePath, relationships, registry, allElementIds) {
|
|
1513
|
+
const { packageName, ownerId } = nativeUsageContext(verify);
|
|
1514
|
+
const sourceId = resolveEndpointId(verify.requirement, packageName, registry, allElementIds);
|
|
1515
|
+
// The verifying case is the owner. A `verify` whose owner is not an
|
|
1516
|
+
// extracted element — a bare `verification def`, say — has no second end
|
|
1517
|
+
// to bind, so it stays a parse fact and not a graph fact.
|
|
1518
|
+
const targetId = ownerId ? resolveEndpointId(ownerId, packageName, registry, allElementIds) : undefined;
|
|
1519
|
+
if (!sourceId || !targetId)
|
|
1520
|
+
return;
|
|
1521
|
+
relationships.push(nativeTraceEdge('verifiedBy', sourceId, targetId, filePath));
|
|
673
1522
|
}
|
|
674
1523
|
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
675
1524
|
function extractAttributes(body) {
|
|
@@ -677,7 +1526,7 @@ function extractAttributes(body) {
|
|
|
677
1526
|
return {};
|
|
678
1527
|
const attrs = {};
|
|
679
1528
|
for (const member of body) {
|
|
680
|
-
if (member.$type === 'AttributeMember' || member.$type === 'RefMember') {
|
|
1529
|
+
if (member.$type === 'AttributeMember' || member.$type === 'RefMember' || member.$type === 'MetadataFeatureMember') {
|
|
681
1530
|
const attr = member;
|
|
682
1531
|
if (attr.value) {
|
|
683
1532
|
attrs[attr.name] = extractAttributeValue(attr.value);
|
|
@@ -685,6 +1534,46 @@ function extractAttributes(body) {
|
|
|
685
1534
|
else if (attr.type) {
|
|
686
1535
|
attrs[attr.name] = `<${attr.type}>`;
|
|
687
1536
|
}
|
|
1537
|
+
else if (attr.body?.length) {
|
|
1538
|
+
// Structured value: the members of an `attribute def` assigned
|
|
1539
|
+
// inline, e.g. `attribute :>> bounds { attribute :>> x = 0.1; }`.
|
|
1540
|
+
// Flattened to dotted keys ("bounds.x") so the value lands in
|
|
1541
|
+
// the same flat map every consumer already reads. Without this
|
|
1542
|
+
// branch the whole assignment is dropped and the model carries
|
|
1543
|
+
// no record of it.
|
|
1544
|
+
for (const [key, value] of Object.entries(extractAttributes(attr.body))) {
|
|
1545
|
+
attrs[`${attr.name}.${key}`] = value;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
return attrs;
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Read the standard `Rationale`/`StatusInfo` metadata (ModelingMetadata.sysml)
|
|
1554
|
+
* off a connection usage's body into the same flat attribute keys the deleted
|
|
1555
|
+
* `MemoRelationship.rationale`/`.status` used to occupy (R10-S5, 2026-08-13).
|
|
1556
|
+
*
|
|
1557
|
+
* `extractAttributes` only walks `AttributeMember`/`RefMember`/
|
|
1558
|
+
* `MetadataFeatureMember`; a `MetadataApplication` in a usage body (the `@Foo
|
|
1559
|
+
* {...}` form) is invisible to it, so without this a `@Rationale`/`@StatusInfo`
|
|
1560
|
+
* annotation would parse and silently vanish from the model — the same
|
|
1561
|
+
* BindingUsage/ExposeMember shape this epic exists to stop repeating.
|
|
1562
|
+
*/
|
|
1563
|
+
function extractRelationshipMetadata(body) {
|
|
1564
|
+
if (!body)
|
|
1565
|
+
return {};
|
|
1566
|
+
const attrs = {};
|
|
1567
|
+
for (const member of body) {
|
|
1568
|
+
if (member.$type !== 'MetadataApplication')
|
|
1569
|
+
continue;
|
|
1570
|
+
const metadataType = member.type?.split('::').pop();
|
|
1571
|
+
const fields = extractAttributes(member.body);
|
|
1572
|
+
if (metadataType === 'Rationale' && fields.text) {
|
|
1573
|
+
attrs.rationale = fields.text;
|
|
1574
|
+
}
|
|
1575
|
+
else if (metadataType === 'StatusInfo' && fields.status) {
|
|
1576
|
+
attrs.status = fields.status;
|
|
688
1577
|
}
|
|
689
1578
|
}
|
|
690
1579
|
return attrs;
|
|
@@ -742,7 +1631,15 @@ function resolveRef(ref) {
|
|
|
742
1631
|
* are registered under their leaf name, so when the full reference is not a
|
|
743
1632
|
* known element id, resolve its last dot segment instead.
|
|
744
1633
|
*/
|
|
745
|
-
function resolveEndpointId(
|
|
1634
|
+
function resolveEndpointId(
|
|
1635
|
+
// An endpoint can parse without a reference — the Release examples contain
|
|
1636
|
+
// connection forms the MEMO grammar accepts structurally but cannot bind.
|
|
1637
|
+
// An unresolvable endpoint drops the relationship at the call site, which
|
|
1638
|
+
// is the same outcome as any other unresolved reference; crashing the whole
|
|
1639
|
+
// build over it is not (§1.1 — the compiler reports, it does not refuse).
|
|
1640
|
+
ref, packageName, registry, allElementIds) {
|
|
1641
|
+
if (!ref)
|
|
1642
|
+
return undefined;
|
|
746
1643
|
const direct = registry.resolveElementId(ref, packageName, allElementIds) || resolveRef(ref);
|
|
747
1644
|
if (direct && allElementIds.has(direct))
|
|
748
1645
|
return direct;
|
|
@@ -755,11 +1652,8 @@ function resolveEndpointId(ref, packageName, registry, allElementIds) {
|
|
|
755
1652
|
return direct;
|
|
756
1653
|
}
|
|
757
1654
|
/**
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
* "Mitigates" → "mitigates", "TraceTo" → "traceTo", "AllocateTo" → "allocateTo"
|
|
1655
|
+
* Relationship type names are normalized by the shared helper in `naming.ts`,
|
|
1656
|
+
* which is the single definition of the source-name → model-key rule.
|
|
761
1657
|
*/
|
|
762
|
-
|
|
763
|
-
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
764
|
-
}
|
|
1658
|
+
const normalizeRelType = toModelType;
|
|
765
1659
|
//# sourceMappingURL=builder.js.map
|