@memoarchitect/tools 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -26
- package/corpus/README.md +20 -36
- package/package.json +9 -10
- package/packages/tools/lib/analysis/impact.d.ts +30 -0
- package/packages/tools/lib/analysis/impact.d.ts.map +1 -1
- package/packages/tools/lib/analysis/impact.js +47 -74
- package/packages/tools/lib/analysis/impact.js.map +1 -1
- package/packages/tools/lib/analysis/interfaces-between.d.ts +36 -0
- package/packages/tools/lib/analysis/interfaces-between.d.ts.map +1 -0
- package/packages/tools/lib/analysis/interfaces-between.js +66 -0
- package/packages/tools/lib/analysis/interfaces-between.js.map +1 -0
- package/packages/tools/lib/analysis/suspect-links.d.ts +45 -0
- package/packages/tools/lib/analysis/suspect-links.d.ts.map +1 -0
- package/packages/tools/lib/analysis/suspect-links.js +66 -0
- package/packages/tools/lib/analysis/suspect-links.js.map +1 -0
- package/packages/tools/lib/analysis-starters.d.ts +2 -0
- package/packages/tools/lib/analysis-starters.d.ts.map +1 -1
- package/packages/tools/lib/analysis-starters.js +73 -68
- package/packages/tools/lib/analysis-starters.js.map +1 -1
- package/packages/tools/lib/authoring/outline-identity.d.ts +34 -0
- package/packages/tools/lib/authoring/outline-identity.d.ts.map +1 -0
- package/packages/tools/lib/authoring/outline-identity.js +95 -0
- package/packages/tools/lib/authoring/outline-identity.js.map +1 -0
- package/packages/tools/lib/authoring/outline-source.d.ts +57 -0
- package/packages/tools/lib/authoring/outline-source.d.ts.map +1 -0
- package/packages/tools/lib/authoring/outline-source.js +203 -0
- package/packages/tools/lib/authoring/outline-source.js.map +1 -0
- package/packages/tools/lib/authoring/source-outline.d.ts +82 -0
- package/packages/tools/lib/authoring/source-outline.d.ts.map +1 -0
- package/packages/tools/lib/authoring/source-outline.js +267 -0
- package/packages/tools/lib/authoring/source-outline.js.map +1 -0
- package/packages/tools/lib/bin/memo.js +181 -632
- package/packages/tools/lib/bin/memo.js.map +1 -1
- package/packages/tools/lib/browser/index.d.ts +12 -0
- package/packages/tools/lib/browser/index.d.ts.map +1 -1
- package/packages/tools/lib/browser/index.js +8 -0
- package/packages/tools/lib/browser/index.js.map +1 -1
- package/packages/tools/lib/cli/project-commands.d.ts +3 -0
- package/packages/tools/lib/cli/project-commands.d.ts.map +1 -0
- package/packages/tools/lib/cli/project-commands.js +577 -0
- package/packages/tools/lib/cli/project-commands.js.map +1 -0
- package/packages/tools/lib/commands/ask.d.ts.map +1 -1
- package/packages/tools/lib/commands/ask.js +10 -18
- package/packages/tools/lib/commands/ask.js.map +1 -1
- package/packages/tools/lib/commands/compile.d.ts +18 -0
- package/packages/tools/lib/commands/compile.d.ts.map +1 -0
- package/packages/tools/lib/commands/compile.js +122 -0
- package/packages/tools/lib/commands/compile.js.map +1 -0
- package/packages/tools/lib/commands/convert.js +2 -2
- package/packages/tools/lib/commands/convert.js.map +1 -1
- package/packages/tools/lib/commands/create-package.js +4 -4
- package/packages/tools/lib/commands/create-package.js.map +1 -1
- package/packages/tools/lib/commands/dev.d.ts +20 -2
- package/packages/tools/lib/commands/dev.d.ts.map +1 -1
- package/packages/tools/lib/commands/dev.js +386 -97
- package/packages/tools/lib/commands/dev.js.map +1 -1
- package/packages/tools/lib/commands/dhf-draft.d.ts.map +1 -1
- package/packages/tools/lib/commands/dhf-draft.js +7 -16
- package/packages/tools/lib/commands/dhf-draft.js.map +1 -1
- package/packages/tools/lib/commands/dhf-init.js +3 -3
- package/packages/tools/lib/commands/dhf-init.js.map +1 -1
- package/packages/tools/lib/commands/dhf-lint.d.ts.map +1 -1
- package/packages/tools/lib/commands/dhf-lint.js +4 -3
- package/packages/tools/lib/commands/dhf-lint.js.map +1 -1
- package/packages/tools/lib/commands/dhf-preview.d.ts.map +1 -1
- package/packages/tools/lib/commands/dhf-preview.js +5 -26
- package/packages/tools/lib/commands/dhf-preview.js.map +1 -1
- package/packages/tools/lib/commands/dhf.d.ts +4 -0
- package/packages/tools/lib/commands/dhf.d.ts.map +1 -1
- package/packages/tools/lib/commands/dhf.js +77 -31
- package/packages/tools/lib/commands/dhf.js.map +1 -1
- package/packages/tools/lib/commands/element.d.ts.map +1 -1
- package/packages/tools/lib/commands/element.js +44 -6
- package/packages/tools/lib/commands/element.js.map +1 -1
- package/packages/tools/lib/commands/export.d.ts +1 -1
- package/packages/tools/lib/commands/export.d.ts.map +1 -1
- package/packages/tools/lib/commands/export.js +25 -18
- 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 -30
- package/packages/tools/lib/commands/generate.js.map +1 -1
- package/packages/tools/lib/commands/ids-rebase.d.ts +15 -0
- package/packages/tools/lib/commands/ids-rebase.d.ts.map +1 -0
- package/packages/tools/lib/commands/ids-rebase.js +133 -0
- package/packages/tools/lib/commands/ids-rebase.js.map +1 -0
- package/packages/tools/lib/commands/import-ea.d.ts +3 -3
- package/packages/tools/lib/commands/import-ea.d.ts.map +1 -1
- package/packages/tools/lib/commands/import-ea.js +12 -9
- package/packages/tools/lib/commands/import-ea.js.map +1 -1
- package/packages/tools/lib/commands/import-owl.d.ts +1 -1
- package/packages/tools/lib/commands/import-owl.js +2 -2
- package/packages/tools/lib/commands/import-owl.js.map +1 -1
- package/packages/tools/lib/commands/import-sysand.d.ts +1 -1
- package/packages/tools/lib/commands/import-sysand.d.ts.map +1 -1
- package/packages/tools/lib/commands/import-sysand.js +15 -6
- package/packages/tools/lib/commands/import-sysand.js.map +1 -1
- package/packages/tools/lib/commands/import.d.ts +13 -0
- package/packages/tools/lib/commands/import.d.ts.map +1 -1
- package/packages/tools/lib/commands/import.js +89 -29
- package/packages/tools/lib/commands/import.js.map +1 -1
- package/packages/tools/lib/commands/init.d.ts +0 -8
- package/packages/tools/lib/commands/init.d.ts.map +1 -1
- package/packages/tools/lib/commands/init.js +56 -51
- package/packages/tools/lib/commands/init.js.map +1 -1
- package/packages/tools/lib/commands/inspect.d.ts.map +1 -1
- package/packages/tools/lib/commands/inspect.js +22 -15
- package/packages/tools/lib/commands/inspect.js.map +1 -1
- package/packages/tools/lib/commands/install.d.ts.map +1 -1
- package/packages/tools/lib/commands/install.js +9 -6
- package/packages/tools/lib/commands/install.js.map +1 -1
- package/packages/tools/lib/commands/interfaces.d.ts +8 -0
- package/packages/tools/lib/commands/interfaces.d.ts.map +1 -0
- package/packages/tools/lib/commands/interfaces.js +71 -0
- package/packages/tools/lib/commands/interfaces.js.map +1 -0
- package/packages/tools/lib/commands/lock.d.ts.map +1 -1
- package/packages/tools/lib/commands/lock.js +13 -6
- package/packages/tools/lib/commands/lock.js.map +1 -1
- package/packages/tools/lib/commands/mcp.js +7 -7
- package/packages/tools/lib/commands/mcp.js.map +1 -1
- package/packages/tools/lib/commands/migrate-layout.d.ts +5 -0
- package/packages/tools/lib/commands/migrate-layout.d.ts.map +1 -0
- package/packages/tools/lib/commands/migrate-layout.js +90 -0
- package/packages/tools/lib/commands/migrate-layout.js.map +1 -0
- package/packages/tools/lib/commands/ontology.d.ts.map +1 -1
- package/packages/tools/lib/commands/ontology.js +26 -22
- package/packages/tools/lib/commands/ontology.js.map +1 -1
- package/packages/tools/lib/commands/pack.d.ts.map +1 -1
- package/packages/tools/lib/commands/pack.js +14 -9
- package/packages/tools/lib/commands/pack.js.map +1 -1
- package/packages/tools/lib/commands/pinned-target.d.ts +12 -0
- package/packages/tools/lib/commands/pinned-target.d.ts.map +1 -0
- package/packages/tools/lib/commands/pinned-target.js +74 -0
- package/packages/tools/lib/commands/pinned-target.js.map +1 -0
- package/packages/tools/lib/commands/plugin.d.ts.map +1 -1
- package/packages/tools/lib/commands/plugin.js +13 -22
- package/packages/tools/lib/commands/plugin.js.map +1 -1
- package/packages/tools/lib/commands/prune.d.ts +5 -0
- package/packages/tools/lib/commands/prune.d.ts.map +1 -0
- package/packages/tools/lib/commands/prune.js +27 -0
- package/packages/tools/lib/commands/prune.js.map +1 -0
- package/packages/tools/lib/commands/retired.d.ts +10 -0
- package/packages/tools/lib/commands/retired.d.ts.map +1 -0
- package/packages/tools/lib/commands/retired.js +35 -0
- package/packages/tools/lib/commands/retired.js.map +1 -0
- package/packages/tools/lib/commands/rules.d.ts +49 -5
- package/packages/tools/lib/commands/rules.d.ts.map +1 -1
- package/packages/tools/lib/commands/rules.js +340 -172
- package/packages/tools/lib/commands/rules.js.map +1 -1
- package/packages/tools/lib/commands/ship-library.d.ts +4 -0
- package/packages/tools/lib/commands/ship-library.d.ts.map +1 -0
- package/packages/tools/lib/commands/ship-library.js +45 -0
- package/packages/tools/lib/commands/ship-library.js.map +1 -0
- package/packages/tools/lib/commands/standards.d.ts +2 -2
- package/packages/tools/lib/commands/standards.d.ts.map +1 -1
- package/packages/tools/lib/commands/standards.js +78 -33
- package/packages/tools/lib/commands/standards.js.map +1 -1
- package/packages/tools/lib/commands/sysand-publish.d.ts +16 -1
- package/packages/tools/lib/commands/sysand-publish.d.ts.map +1 -1
- package/packages/tools/lib/commands/sysand-publish.js +75 -193
- package/packages/tools/lib/commands/sysand-publish.js.map +1 -1
- package/packages/tools/lib/commands/toolchain.d.ts +5 -0
- package/packages/tools/lib/commands/toolchain.d.ts.map +1 -1
- package/packages/tools/lib/commands/toolchain.js +50 -1
- package/packages/tools/lib/commands/toolchain.js.map +1 -1
- package/packages/tools/lib/commands/validate-client.d.ts +11 -0
- package/packages/tools/lib/commands/validate-client.d.ts.map +1 -0
- package/packages/tools/lib/commands/validate-client.js +54 -0
- package/packages/tools/lib/commands/validate-client.js.map +1 -0
- package/packages/tools/lib/commands/validate.d.ts +33 -2
- package/packages/tools/lib/commands/validate.d.ts.map +1 -1
- package/packages/tools/lib/commands/validate.js +432 -186
- package/packages/tools/lib/commands/validate.js.map +1 -1
- package/packages/tools/lib/dhf/device-dhf.d.ts +57 -0
- package/packages/tools/lib/dhf/device-dhf.d.ts.map +1 -0
- package/packages/tools/lib/dhf/device-dhf.js +152 -0
- package/packages/tools/lib/dhf/device-dhf.js.map +1 -0
- package/packages/tools/lib/dhf/dhf-config-v2.d.ts +1 -1
- package/packages/tools/lib/dhf/dhf-config-v2.d.ts.map +1 -1
- package/packages/tools/lib/dhf/query-engine.d.ts +9 -2
- package/packages/tools/lib/dhf/query-engine.d.ts.map +1 -1
- package/packages/tools/lib/dhf/query-engine.js +29 -25
- package/packages/tools/lib/dhf/query-engine.js.map +1 -1
- package/packages/tools/lib/dhf/query-executor.d.ts +1 -1
- package/packages/tools/lib/dhf/query-executor.js +1 -1
- package/packages/tools/lib/dhf/query-executor.js.map +1 -1
- package/packages/tools/lib/dhf/standards-block.js +1 -1
- package/packages/tools/lib/dhf/standards-block.js.map +1 -1
- package/packages/tools/lib/dhf/standards-library.d.ts.map +1 -1
- package/packages/tools/lib/dhf/standards-library.js +16 -9
- package/packages/tools/lib/dhf/standards-library.js.map +1 -1
- package/packages/tools/lib/dhf/standards-report.d.ts +11 -3
- package/packages/tools/lib/dhf/standards-report.d.ts.map +1 -1
- package/packages/tools/lib/dhf/standards-report.js +43 -13
- package/packages/tools/lib/dhf/standards-report.js.map +1 -1
- package/packages/tools/lib/dhf/template-engine.d.ts +2 -0
- package/packages/tools/lib/dhf/template-engine.d.ts.map +1 -1
- package/packages/tools/lib/dhf/template-engine.js +5 -5
- package/packages/tools/lib/dhf/template-engine.js.map +1 -1
- package/packages/tools/lib/import/import-diff.d.ts +31 -1
- package/packages/tools/lib/import/import-diff.d.ts.map +1 -1
- package/packages/tools/lib/import/import-diff.js +91 -19
- package/packages/tools/lib/import/import-diff.js.map +1 -1
- package/packages/tools/lib/import/import-sources.d.ts +21 -0
- package/packages/tools/lib/import/import-sources.d.ts.map +1 -0
- package/packages/tools/lib/import/import-sources.js +36 -0
- package/packages/tools/lib/import/import-sources.js.map +1 -0
- package/packages/tools/lib/import/reqif.d.ts +23 -0
- package/packages/tools/lib/import/reqif.d.ts.map +1 -0
- package/packages/tools/lib/import/reqif.js +151 -0
- package/packages/tools/lib/import/reqif.js.map +1 -0
- package/packages/tools/lib/import/source-import.d.ts +128 -0
- package/packages/tools/lib/import/source-import.d.ts.map +1 -0
- package/packages/tools/lib/import/source-import.js +305 -0
- package/packages/tools/lib/import/source-import.js.map +1 -0
- package/packages/tools/lib/importer/cameo-importer.d.ts.map +1 -1
- package/packages/tools/lib/importer/cameo-importer.js +4 -1
- 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 -1
- package/packages/tools/lib/importer/ea-importer.js.map +1 -1
- package/packages/tools/lib/importer/sysand-importer.d.ts +2 -1
- package/packages/tools/lib/importer/sysand-importer.d.ts.map +1 -1
- package/packages/tools/lib/importer/sysand-importer.js +27 -10
- package/packages/tools/lib/importer/sysand-importer.js.map +1 -1
- package/packages/tools/lib/index.d.ts +20 -6
- package/packages/tools/lib/index.d.ts.map +1 -1
- package/packages/tools/lib/index.js +22 -8
- package/packages/tools/lib/index.js.map +1 -1
- package/packages/tools/lib/llm/draft-engine.js +1 -1
- package/packages/tools/lib/llm/draft-engine.js.map +1 -1
- package/packages/tools/lib/llm/model-context.js +1 -1
- package/packages/tools/lib/llm/model-context.js.map +1 -1
- package/packages/tools/lib/lock.d.ts +37 -2
- package/packages/tools/lib/lock.d.ts.map +1 -1
- package/packages/tools/lib/lock.js +93 -8
- package/packages/tools/lib/lock.js.map +1 -1
- package/packages/tools/lib/mcp/index.js +1 -1
- package/packages/tools/lib/mcp/index.js.map +1 -1
- package/packages/tools/lib/mcp/model-loader.d.ts.map +1 -1
- package/packages/tools/lib/mcp/model-loader.js +6 -18
- package/packages/tools/lib/mcp/model-loader.js.map +1 -1
- package/packages/tools/lib/mcp/server.js +2 -2
- package/packages/tools/lib/mcp/server.js.map +1 -1
- package/packages/tools/lib/mcp/tools.d.ts.map +1 -1
- package/packages/tools/lib/mcp/tools.js +5 -4
- package/packages/tools/lib/mcp/tools.js.map +1 -1
- package/packages/tools/lib/methodology/guide-service.d.ts +28 -0
- package/packages/tools/lib/methodology/guide-service.d.ts.map +1 -0
- package/packages/tools/lib/methodology/guide-service.js +32 -0
- package/packages/tools/lib/methodology/guide-service.js.map +1 -0
- package/packages/tools/lib/methodology/guide.d.ts +56 -0
- package/packages/tools/lib/methodology/guide.d.ts.map +1 -0
- package/packages/tools/lib/methodology/guide.js +80 -0
- package/packages/tools/lib/methodology/guide.js.map +1 -0
- package/packages/tools/lib/model/census-projects.d.ts +26 -0
- package/packages/tools/lib/model/census-projects.d.ts.map +1 -0
- package/packages/tools/lib/model/census-projects.js +53 -0
- package/packages/tools/lib/model/census-projects.js.map +1 -0
- package/packages/tools/lib/model/census.d.ts +103 -0
- package/packages/tools/lib/model/census.d.ts.map +1 -0
- package/packages/tools/lib/model/census.js +229 -0
- package/packages/tools/lib/model/census.js.map +1 -0
- package/packages/tools/lib/model/complete-model.d.ts +52 -0
- package/packages/tools/lib/model/complete-model.d.ts.map +1 -0
- package/packages/tools/lib/model/complete-model.js +287 -0
- package/packages/tools/lib/model/complete-model.js.map +1 -0
- package/packages/tools/lib/model/config-loader.d.ts +8 -3
- package/packages/tools/lib/model/config-loader.d.ts.map +1 -1
- package/packages/tools/lib/model/config-loader.js +37 -6
- package/packages/tools/lib/model/config-loader.js.map +1 -1
- package/packages/tools/lib/model/config.d.ts +21 -7
- package/packages/tools/lib/model/config.d.ts.map +1 -1
- package/packages/tools/lib/model/effective-scope.d.ts +55 -28
- package/packages/tools/lib/model/effective-scope.d.ts.map +1 -1
- package/packages/tools/lib/model/effective-scope.js +96 -35
- package/packages/tools/lib/model/effective-scope.js.map +1 -1
- package/packages/tools/lib/model/element-index.d.ts +207 -0
- package/packages/tools/lib/model/element-index.d.ts.map +1 -0
- package/packages/tools/lib/model/element-index.js +316 -0
- package/packages/tools/lib/model/element-index.js.map +1 -0
- package/packages/tools/lib/model/id-rebase.d.ts +35 -0
- package/packages/tools/lib/model/id-rebase.d.ts.map +1 -0
- package/packages/tools/lib/model/id-rebase.js +199 -0
- package/packages/tools/lib/model/id-rebase.js.map +1 -0
- package/packages/tools/lib/model/identity-registry.d.ts +34 -3
- package/packages/tools/lib/model/identity-registry.d.ts.map +1 -1
- package/packages/tools/lib/model/identity-registry.js +40 -7
- package/packages/tools/lib/model/identity-registry.js.map +1 -1
- package/packages/tools/lib/model/impact.d.ts +75 -0
- package/packages/tools/lib/model/impact.d.ts.map +1 -0
- package/packages/tools/lib/model/impact.js +167 -0
- package/packages/tools/lib/model/impact.js.map +1 -0
- package/packages/tools/lib/model/ir-identity.d.ts +3 -51
- package/packages/tools/lib/model/ir-identity.d.ts.map +1 -1
- package/packages/tools/lib/model/ir-identity.js +14 -121
- package/packages/tools/lib/model/ir-identity.js.map +1 -1
- package/packages/tools/lib/model/kind-registry.d.ts +66 -22
- package/packages/tools/lib/model/kind-registry.d.ts.map +1 -1
- package/packages/tools/lib/model/kind-registry.js +104 -145
- package/packages/tools/lib/model/kind-registry.js.map +1 -1
- package/packages/tools/lib/model/manifest.d.ts +2 -2
- package/packages/tools/lib/model/manifest.d.ts.map +1 -1
- package/packages/tools/lib/model/manifest.js +5 -4
- package/packages/tools/lib/model/manifest.js.map +1 -1
- package/packages/tools/lib/model/methodology-loader.d.ts +11 -2
- package/packages/tools/lib/model/methodology-loader.d.ts.map +1 -1
- package/packages/tools/lib/model/methodology-loader.js +24 -130
- package/packages/tools/lib/model/methodology-loader.js.map +1 -1
- package/packages/tools/lib/model/methodology-resolver.d.ts +71 -6
- package/packages/tools/lib/model/methodology-resolver.d.ts.map +1 -1
- package/packages/tools/lib/model/methodology-resolver.js +210 -24
- package/packages/tools/lib/model/methodology-resolver.js.map +1 -1
- package/packages/tools/lib/model/model-diff.d.ts +73 -0
- package/packages/tools/lib/model/model-diff.d.ts.map +1 -0
- package/packages/tools/lib/model/model-diff.js +91 -0
- package/packages/tools/lib/model/model-diff.js.map +1 -0
- package/packages/tools/lib/model/narrow-model.d.ts +9 -0
- package/packages/tools/lib/model/narrow-model.d.ts.map +1 -0
- package/packages/tools/lib/model/narrow-model.js +54 -0
- package/packages/tools/lib/model/narrow-model.js.map +1 -0
- package/packages/tools/lib/model/native-project.d.ts +92 -11
- package/packages/tools/lib/model/native-project.d.ts.map +1 -1
- package/packages/tools/lib/model/native-project.js +163 -267
- package/packages/tools/lib/model/native-project.js.map +1 -1
- package/packages/tools/lib/model/ontology-loader.d.ts +10 -61
- package/packages/tools/lib/model/ontology-loader.d.ts.map +1 -1
- package/packages/tools/lib/model/ontology-loader.js +11 -512
- package/packages/tools/lib/model/ontology-loader.js.map +1 -1
- package/packages/tools/lib/model/package-manifest.d.ts +8 -2
- package/packages/tools/lib/model/package-manifest.d.ts.map +1 -1
- package/packages/tools/lib/model/package-manifest.js +14 -2
- package/packages/tools/lib/model/package-manifest.js.map +1 -1
- package/packages/tools/lib/model/pinned.d.ts +216 -0
- package/packages/tools/lib/model/pinned.d.ts.map +1 -0
- package/packages/tools/lib/model/pinned.js +481 -0
- package/packages/tools/lib/model/pinned.js.map +1 -0
- package/packages/tools/lib/model/project-conversion.d.ts +3 -2
- package/packages/tools/lib/model/project-conversion.d.ts.map +1 -1
- package/packages/tools/lib/model/project-conversion.js +55 -10
- package/packages/tools/lib/model/project-conversion.js.map +1 -1
- package/packages/tools/lib/model/project-settings.d.ts +10 -0
- package/packages/tools/lib/model/project-settings.d.ts.map +1 -0
- package/packages/tools/lib/model/project-settings.js +48 -0
- package/packages/tools/lib/model/project-settings.js.map +1 -0
- package/packages/tools/lib/model/relation-selection.d.ts +25 -0
- package/packages/tools/lib/model/relation-selection.d.ts.map +1 -0
- package/packages/tools/lib/model/relation-selection.js +65 -0
- package/packages/tools/lib/model/relation-selection.js.map +1 -0
- package/packages/tools/lib/model/relationship-legality.d.ts +6 -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 +21 -8
- package/packages/tools/lib/model/relationship-registry.d.ts.map +1 -1
- package/packages/tools/lib/model/relationship-registry.js +77 -129
- package/packages/tools/lib/model/relationship-registry.js.map +1 -1
- package/packages/tools/lib/model/relationship-subjects.d.ts +28 -0
- package/packages/tools/lib/model/relationship-subjects.d.ts.map +1 -0
- package/packages/tools/lib/model/relationship-subjects.js +126 -0
- package/packages/tools/lib/model/relationship-subjects.js.map +1 -0
- package/packages/tools/lib/model/release-target.d.ts +12 -0
- package/packages/tools/lib/model/release-target.d.ts.map +1 -0
- package/packages/tools/lib/model/release-target.js +35 -0
- package/packages/tools/lib/model/release-target.js.map +1 -0
- package/packages/tools/lib/model/selector-vocabulary.d.ts +47 -0
- package/packages/tools/lib/model/selector-vocabulary.d.ts.map +1 -0
- package/packages/tools/lib/model/selector-vocabulary.js +181 -0
- package/packages/tools/lib/model/selector-vocabulary.js.map +1 -0
- package/packages/tools/lib/model/semantic.d.ts +99 -7
- package/packages/tools/lib/model/semantic.d.ts.map +1 -1
- package/packages/tools/lib/model/semantic.js +13 -1
- package/packages/tools/lib/model/semantic.js.map +1 -1
- package/packages/tools/lib/model/settings-boundary.d.ts.map +1 -1
- package/packages/tools/lib/model/settings-boundary.js +9 -8
- package/packages/tools/lib/model/settings-boundary.js.map +1 -1
- package/packages/tools/lib/model/short-id.d.ts.map +1 -1
- package/packages/tools/lib/model/short-id.js +4 -0
- package/packages/tools/lib/model/short-id.js.map +1 -1
- package/packages/tools/lib/model/source-graph.d.ts +9 -7
- package/packages/tools/lib/model/source-graph.d.ts.map +1 -1
- package/packages/tools/lib/model/source-graph.js +19 -24
- package/packages/tools/lib/model/source-graph.js.map +1 -1
- package/packages/tools/lib/model/source-provenance.d.ts +5 -1
- package/packages/tools/lib/model/source-provenance.d.ts.map +1 -1
- package/packages/tools/lib/model/source-provenance.js.map +1 -1
- package/packages/tools/lib/model/sysml-files.js +1 -1
- package/packages/tools/lib/model/sysml-ir.d.ts +2 -5
- package/packages/tools/lib/model/sysml-ir.d.ts.map +1 -1
- package/packages/tools/lib/model/sysml-ir.js +1 -100
- package/packages/tools/lib/model/sysml-ir.js.map +1 -1
- package/packages/tools/lib/model/toolchain-merge.d.ts +4 -0
- package/packages/tools/lib/model/toolchain-merge.d.ts.map +1 -0
- package/packages/tools/lib/model/toolchain-merge.js +34 -0
- package/packages/tools/lib/model/toolchain-merge.js.map +1 -0
- package/packages/tools/lib/model/user-settings.d.ts +13 -0
- package/packages/tools/lib/model/user-settings.d.ts.map +1 -0
- package/packages/tools/lib/model/user-settings.js +83 -0
- package/packages/tools/lib/model/user-settings.js.map +1 -0
- package/packages/tools/lib/model/variability.d.ts +56 -0
- package/packages/tools/lib/model/variability.d.ts.map +1 -0
- package/packages/tools/lib/model/variability.js +116 -0
- package/packages/tools/lib/model/variability.js.map +1 -0
- package/packages/tools/lib/model/version-range.d.ts +2 -0
- package/packages/tools/lib/model/version-range.d.ts.map +1 -0
- package/packages/tools/lib/model/version-range.js +37 -0
- package/packages/tools/lib/model/version-range.js.map +1 -0
- package/packages/tools/lib/model/view-deriver.d.ts +16 -0
- package/packages/tools/lib/model/view-deriver.d.ts.map +1 -1
- package/packages/tools/lib/model/view-deriver.js +129 -30
- package/packages/tools/lib/model/view-deriver.js.map +1 -1
- package/packages/tools/lib/model/view-layout-block.d.ts +81 -0
- package/packages/tools/lib/model/view-layout-block.d.ts.map +1 -0
- package/packages/tools/lib/model/view-layout-block.js +525 -0
- package/packages/tools/lib/model/view-layout-block.js.map +1 -0
- package/packages/tools/lib/model/view-layout-migration.d.ts +54 -0
- package/packages/tools/lib/model/view-layout-migration.d.ts.map +1 -0
- package/packages/tools/lib/model/view-layout-migration.js +156 -0
- package/packages/tools/lib/model/view-layout-migration.js.map +1 -0
- package/packages/tools/lib/model/workspace-membership.d.ts +99 -0
- package/packages/tools/lib/model/workspace-membership.d.ts.map +1 -0
- package/packages/tools/lib/model/workspace-membership.js +281 -0
- package/packages/tools/lib/model/workspace-membership.js.map +1 -0
- package/packages/tools/lib/ontology/owl-exporter.d.ts +1 -1
- package/packages/tools/lib/ontology/owl-exporter.d.ts.map +1 -1
- package/packages/tools/lib/ontology/owl-exporter.js +1 -1
- package/packages/tools/lib/ontology/owl-exporter.js.map +1 -1
- package/packages/tools/lib/operations/ai-authoring.d.ts.map +1 -1
- package/packages/tools/lib/operations/ai-authoring.js +7 -5
- package/packages/tools/lib/operations/ai-authoring.js.map +1 -1
- package/packages/tools/lib/operations/authoring.d.ts +10 -4
- package/packages/tools/lib/operations/authoring.d.ts.map +1 -1
- package/packages/tools/lib/operations/authoring.js +27 -11
- package/packages/tools/lib/operations/authoring.js.map +1 -1
- 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 +1 -0
- package/packages/tools/lib/operations/index.js.map +1 -1
- package/packages/tools/lib/operations/project-snapshot.d.ts.map +1 -1
- package/packages/tools/lib/operations/project-snapshot.js +7 -13
- package/packages/tools/lib/operations/project-snapshot.js.map +1 -1
- package/packages/tools/lib/plugin/plugin-scaffold.js +2 -2
- package/packages/tools/lib/plugin/plugin-scaffold.js.map +1 -1
- package/packages/tools/lib/protocol/messages.d.ts +375 -7
- package/packages/tools/lib/protocol/messages.d.ts.map +1 -1
- package/packages/tools/lib/serializer/csv-io.d.ts +37 -29
- package/packages/tools/lib/serializer/csv-io.d.ts.map +1 -1
- package/packages/tools/lib/serializer/csv-io.js +64 -31
- package/packages/tools/lib/serializer/csv-io.js.map +1 -1
- package/packages/tools/lib/serializer/sysml-generator.d.ts +15 -2
- package/packages/tools/lib/serializer/sysml-generator.d.ts.map +1 -1
- package/packages/tools/lib/serializer/sysml-generator.js +45 -17
- package/packages/tools/lib/serializer/sysml-generator.js.map +1 -1
- package/packages/tools/lib/server/conflict-policy.js +1 -1
- package/packages/tools/lib/server/conflict-policy.js.map +1 -1
- package/packages/tools/lib/server/dashboard-store.d.ts +1 -7
- package/packages/tools/lib/server/dashboard-store.d.ts.map +1 -1
- package/packages/tools/lib/server/dashboard-store.js +3 -14
- package/packages/tools/lib/server/dashboard-store.js.map +1 -1
- package/packages/tools/lib/server/dev-server.d.ts +48 -1
- package/packages/tools/lib/server/dev-server.d.ts.map +1 -1
- package/packages/tools/lib/server/dev-server.js +529 -80
- package/packages/tools/lib/server/dev-server.js.map +1 -1
- package/packages/tools/lib/server/dev-validate.d.ts +30 -0
- package/packages/tools/lib/server/dev-validate.d.ts.map +1 -0
- package/packages/tools/lib/server/dev-validate.js +82 -0
- package/packages/tools/lib/server/dev-validate.js.map +1 -0
- package/packages/tools/lib/server/element-writer.d.ts +4 -1
- package/packages/tools/lib/server/element-writer.d.ts.map +1 -1
- package/packages/tools/lib/server/element-writer.js +56 -35
- package/packages/tools/lib/server/element-writer.js.map +1 -1
- package/packages/tools/lib/server/mutation-domain.d.ts +10 -0
- package/packages/tools/lib/server/mutation-domain.d.ts.map +1 -1
- package/packages/tools/lib/server/mutation-domain.js +45 -8
- package/packages/tools/lib/server/mutation-domain.js.map +1 -1
- package/packages/tools/lib/server/package-source.d.ts +13 -3
- package/packages/tools/lib/server/package-source.d.ts.map +1 -1
- package/packages/tools/lib/server/package-source.js +31 -39
- package/packages/tools/lib/server/package-source.js.map +1 -1
- package/packages/tools/lib/server/package-writer.d.ts +19 -6
- package/packages/tools/lib/server/package-writer.d.ts.map +1 -1
- package/packages/tools/lib/server/package-writer.js +90 -39
- package/packages/tools/lib/server/package-writer.js.map +1 -1
- package/packages/tools/lib/server/persistor.d.ts +33 -7
- package/packages/tools/lib/server/persistor.d.ts.map +1 -1
- package/packages/tools/lib/server/persistor.js +63 -48
- package/packages/tools/lib/server/persistor.js.map +1 -1
- package/packages/tools/lib/server/project-gitignore.d.ts +9 -0
- package/packages/tools/lib/server/project-gitignore.d.ts.map +1 -0
- package/packages/tools/lib/server/project-gitignore.js +27 -0
- package/packages/tools/lib/server/project-gitignore.js.map +1 -0
- package/packages/tools/lib/server/relationship-writer.d.ts +31 -2
- package/packages/tools/lib/server/relationship-writer.d.ts.map +1 -1
- package/packages/tools/lib/server/relationship-writer.js +255 -95
- package/packages/tools/lib/server/relationship-writer.js.map +1 -1
- package/packages/tools/lib/server/release-writer.d.ts +46 -0
- package/packages/tools/lib/server/release-writer.d.ts.map +1 -0
- package/packages/tools/lib/server/release-writer.js +133 -0
- package/packages/tools/lib/server/release-writer.js.map +1 -0
- package/packages/tools/lib/server/rule-policy-writer.d.ts +17 -4
- package/packages/tools/lib/server/rule-policy-writer.d.ts.map +1 -1
- package/packages/tools/lib/server/rule-policy-writer.js +92 -7
- package/packages/tools/lib/server/rule-policy-writer.js.map +1 -1
- package/packages/tools/lib/server/rule-service.d.ts +50 -0
- package/packages/tools/lib/server/rule-service.d.ts.map +1 -0
- package/packages/tools/lib/server/rule-service.js +89 -0
- package/packages/tools/lib/server/rule-service.js.map +1 -0
- package/packages/tools/lib/server/rule-writer.d.ts +87 -0
- package/packages/tools/lib/server/rule-writer.d.ts.map +1 -0
- package/packages/tools/lib/server/rule-writer.js +165 -0
- package/packages/tools/lib/server/rule-writer.js.map +1 -0
- package/packages/tools/lib/server/suspect-review.d.ts +11 -0
- package/packages/tools/lib/server/suspect-review.d.ts.map +1 -0
- package/packages/tools/lib/server/suspect-review.js +28 -0
- package/packages/tools/lib/server/suspect-review.js.map +1 -0
- package/packages/tools/lib/server/sysml-notation.d.ts +1 -1
- package/packages/tools/lib/server/sysml-notation.d.ts.map +1 -1
- package/packages/tools/lib/server/sysml-notation.js +5 -0
- package/packages/tools/lib/server/sysml-notation.js.map +1 -1
- package/packages/tools/lib/server/user-preferences.d.ts +8 -0
- package/packages/tools/lib/server/user-preferences.d.ts.map +1 -0
- package/packages/tools/lib/server/user-preferences.js +47 -0
- package/packages/tools/lib/server/user-preferences.js.map +1 -0
- package/packages/tools/lib/server/version-servers.d.ts +60 -0
- package/packages/tools/lib/server/version-servers.d.ts.map +1 -0
- package/packages/tools/lib/server/version-servers.js +106 -0
- package/packages/tools/lib/server/version-servers.js.map +1 -0
- package/packages/tools/lib/server/view-layout-store.d.ts +28 -13
- package/packages/tools/lib/server/view-layout-store.d.ts.map +1 -1
- package/packages/tools/lib/server/view-layout-store.js +106 -106
- package/packages/tools/lib/server/view-layout-store.js.map +1 -1
- package/packages/tools/lib/server/view-writer.d.ts +22 -2
- package/packages/tools/lib/server/view-writer.d.ts.map +1 -1
- package/packages/tools/lib/server/view-writer.js +99 -44
- package/packages/tools/lib/server/view-writer.js.map +1 -1
- package/packages/tools/lib/server/write-guard.d.ts +7 -0
- package/packages/tools/lib/server/write-guard.d.ts.map +1 -0
- package/packages/tools/lib/server/write-guard.js +77 -0
- package/packages/tools/lib/server/write-guard.js.map +1 -0
- package/packages/tools/lib/stage2/api-model.d.ts +160 -0
- package/packages/tools/lib/stage2/api-model.d.ts.map +1 -0
- package/packages/tools/lib/stage2/api-model.js +341 -0
- package/packages/tools/lib/stage2/api-model.js.map +1 -0
- package/packages/tools/lib/stage2/build-from-api.d.ts +47 -0
- package/packages/tools/lib/stage2/build-from-api.d.ts.map +1 -0
- package/packages/tools/lib/stage2/build-from-api.js +1462 -0
- package/packages/tools/lib/stage2/build-from-api.js.map +1 -0
- package/packages/tools/lib/stage2/guide-from-api.d.ts +38 -0
- package/packages/tools/lib/stage2/guide-from-api.d.ts.map +1 -0
- package/packages/tools/lib/stage2/guide-from-api.js +97 -0
- package/packages/tools/lib/stage2/guide-from-api.js.map +1 -0
- package/packages/tools/lib/stage2/handoff-files.d.ts +13 -0
- package/packages/tools/lib/stage2/handoff-files.d.ts.map +1 -0
- package/packages/tools/lib/stage2/handoff-files.js +32 -0
- package/packages/tools/lib/stage2/handoff-files.js.map +1 -0
- package/packages/tools/lib/stage2/methodology-from-api.d.ts +10 -0
- package/packages/tools/lib/stage2/methodology-from-api.d.ts.map +1 -0
- package/packages/tools/lib/stage2/methodology-from-api.js +109 -0
- package/packages/tools/lib/stage2/methodology-from-api.js.map +1 -0
- package/packages/tools/lib/stage2/package-metadata-from-api.d.ts +15 -0
- package/packages/tools/lib/stage2/package-metadata-from-api.d.ts.map +1 -0
- package/packages/tools/lib/stage2/package-metadata-from-api.js +238 -0
- package/packages/tools/lib/stage2/package-metadata-from-api.js.map +1 -0
- package/packages/tools/lib/stage2/project-from-api.d.ts +60 -0
- package/packages/tools/lib/stage2/project-from-api.d.ts.map +1 -0
- package/packages/tools/lib/stage2/project-from-api.js +328 -0
- package/packages/tools/lib/stage2/project-from-api.js.map +1 -0
- package/packages/tools/lib/stage2/registries-from-api.d.ts +68 -0
- package/packages/tools/lib/stage2/registries-from-api.d.ts.map +1 -0
- package/packages/tools/lib/stage2/registries-from-api.js +313 -0
- package/packages/tools/lib/stage2/registries-from-api.js.map +1 -0
- package/packages/tools/lib/stage2/stage2-from-handoff.d.ts +26 -0
- package/packages/tools/lib/stage2/stage2-from-handoff.d.ts.map +1 -0
- package/packages/tools/lib/stage2/stage2-from-handoff.js +34 -0
- package/packages/tools/lib/stage2/stage2-from-handoff.js.map +1 -0
- package/packages/tools/lib/stage2/sysml-names.d.ts +9 -0
- package/packages/tools/lib/stage2/sysml-names.d.ts.map +1 -0
- package/packages/tools/lib/stage2/sysml-names.js +39 -0
- package/packages/tools/lib/stage2/sysml-names.js.map +1 -0
- package/packages/tools/lib/toolchain/default-registry.d.ts +2 -2
- package/packages/tools/lib/toolchain/default-registry.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/default-registry.js +9 -5
- package/packages/tools/lib/toolchain/default-registry.js.map +1 -1
- package/packages/tools/lib/toolchain/diagnostic.d.ts +2 -2
- package/packages/tools/lib/toolchain/diagnostic.js +1 -1
- package/packages/tools/lib/toolchain/diagnostic.js.map +1 -1
- package/packages/tools/lib/toolchain/effective.d.ts +25 -17
- package/packages/tools/lib/toolchain/effective.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/effective.js +45 -40
- package/packages/tools/lib/toolchain/effective.js.map +1 -1
- package/packages/tools/lib/toolchain/exceptions.d.ts +27 -0
- package/packages/tools/lib/toolchain/exceptions.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/exceptions.js +77 -0
- package/packages/tools/lib/toolchain/exceptions.js.map +1 -0
- package/packages/tools/lib/toolchain/index.d.ts +2 -2
- package/packages/tools/lib/toolchain/index.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/index.js +2 -2
- package/packages/tools/lib/toolchain/index.js.map +1 -1
- package/packages/tools/lib/toolchain/operations.d.ts +45 -10
- package/packages/tools/lib/toolchain/operations.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/operations.js +107 -8
- package/packages/tools/lib/toolchain/operations.js.map +1 -1
- package/packages/tools/lib/toolchain/ownership.d.ts +13 -0
- package/packages/tools/lib/toolchain/ownership.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/ownership.js +57 -0
- package/packages/tools/lib/toolchain/ownership.js.map +1 -0
- package/packages/tools/lib/toolchain/process.d.ts +2 -2
- package/packages/tools/lib/toolchain/process.js +2 -2
- package/packages/tools/lib/toolchain/project-config.d.ts +4 -0
- package/packages/tools/lib/toolchain/project-config.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/project-config.js +13 -0
- package/packages/tools/lib/toolchain/project-config.js.map +1 -0
- package/packages/tools/lib/toolchain/project-model.d.ts +75 -0
- package/packages/tools/lib/toolchain/project-model.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/project-model.js +92 -0
- package/packages/tools/lib/toolchain/project-model.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/internal-package.d.ts +6 -0
- package/packages/tools/lib/toolchain/providers/internal-package.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/internal-package.js +47 -0
- package/packages/tools/lib/toolchain/providers/internal-package.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-check.d.ts +20 -0
- package/packages/tools/lib/toolchain/providers/opensysml-check.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-check.js +95 -0
- package/packages/tools/lib/toolchain/providers/opensysml-check.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-compact.d.ts +17 -0
- package/packages/tools/lib/toolchain/providers/opensysml-compact.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-compact.js +69 -0
- package/packages/tools/lib/toolchain/providers/opensysml-compact.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-lowering.d.ts +50 -0
- package/packages/tools/lib/toolchain/providers/opensysml-lowering.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-lowering.js +646 -0
- package/packages/tools/lib/toolchain/providers/opensysml-lowering.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-names.d.ts +16 -0
- package/packages/tools/lib/toolchain/providers/opensysml-names.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml-names.js +37 -0
- package/packages/tools/lib/toolchain/providers/opensysml-names.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml.d.ts +88 -0
- package/packages/tools/lib/toolchain/providers/opensysml.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/opensysml.js +178 -0
- package/packages/tools/lib/toolchain/providers/opensysml.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/recommended.d.ts +2 -0
- package/packages/tools/lib/toolchain/providers/recommended.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/recommended.js +13 -0
- package/packages/tools/lib/toolchain/providers/recommended.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/sysand-project.d.ts +60 -0
- package/packages/tools/lib/toolchain/providers/sysand-project.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/sysand-project.js +160 -0
- package/packages/tools/lib/toolchain/providers/sysand-project.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/sysand.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/providers/sysand.js +26 -2
- package/packages/tools/lib/toolchain/providers/sysand.js.map +1 -1
- package/packages/tools/lib/toolchain/providers/syside-lowering.d.ts +29 -0
- package/packages/tools/lib/toolchain/providers/syside-lowering.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/syside-lowering.js +497 -0
- package/packages/tools/lib/toolchain/providers/syside-lowering.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/syside-python.d.ts +9 -0
- package/packages/tools/lib/toolchain/providers/syside-python.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/providers/syside-python.js +69 -0
- package/packages/tools/lib/toolchain/providers/syside-python.js.map +1 -0
- package/packages/tools/lib/toolchain/providers/syside.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/providers/syside.js +2 -0
- package/packages/tools/lib/toolchain/providers/syside.js.map +1 -1
- package/packages/tools/lib/toolchain/registry.d.ts +118 -21
- package/packages/tools/lib/toolchain/registry.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/registry.js +18 -24
- package/packages/tools/lib/toolchain/registry.js.map +1 -1
- package/packages/tools/lib/toolchain/schema.d.ts +6 -5
- package/packages/tools/lib/toolchain/schema.d.ts.map +1 -1
- package/packages/tools/lib/toolchain/schema.js +8 -13
- package/packages/tools/lib/toolchain/schema.js.map +1 -1
- package/packages/tools/lib/toolchain/shipped-library.d.ts +28 -0
- package/packages/tools/lib/toolchain/shipped-library.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/shipped-library.js +120 -0
- package/packages/tools/lib/toolchain/shipped-library.js.map +1 -0
- package/packages/tools/lib/toolchain/source-fingerprint.d.ts +2 -0
- package/packages/tools/lib/toolchain/source-fingerprint.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/source-fingerprint.js +30 -0
- package/packages/tools/lib/toolchain/source-fingerprint.js.map +1 -0
- package/packages/tools/lib/toolchain/user-settings-status.d.ts +51 -0
- package/packages/tools/lib/toolchain/user-settings-status.d.ts.map +1 -0
- package/packages/tools/lib/toolchain/user-settings-status.js +104 -0
- package/packages/tools/lib/toolchain/user-settings-status.js.map +1 -0
- package/packages/tools/lib/validator/architecture-validator.d.ts.map +1 -1
- package/packages/tools/lib/validator/architecture-validator.js +2 -1
- package/packages/tools/lib/validator/architecture-validator.js.map +1 -1
- package/packages/tools/lib/validator/behavior-validator.js +1 -1
- package/packages/tools/lib/validator/behavior-validator.js.map +1 -1
- package/packages/tools/lib/validator/builtin-rules.js +1 -1
- package/packages/tools/lib/validator/builtin-rules.js.map +1 -1
- package/packages/tools/lib/validator/constraint-eval.d.ts +30 -4
- package/packages/tools/lib/validator/constraint-eval.d.ts.map +1 -1
- package/packages/tools/lib/validator/constraint-eval.js +101 -59
- package/packages/tools/lib/validator/constraint-eval.js.map +1 -1
- package/packages/tools/lib/validator/constraint-loader-api.d.ts +22 -0
- package/packages/tools/lib/validator/constraint-loader-api.d.ts.map +1 -0
- package/packages/tools/lib/validator/constraint-loader-api.js +160 -0
- package/packages/tools/lib/validator/constraint-loader-api.js.map +1 -0
- package/packages/tools/lib/validator/constraint-loader.d.ts +22 -18
- package/packages/tools/lib/validator/constraint-loader.d.ts.map +1 -1
- package/packages/tools/lib/validator/constraint-loader.js +33 -141
- package/packages/tools/lib/validator/constraint-loader.js.map +1 -1
- package/packages/tools/lib/validator/rule-clauses.d.ts +51 -0
- package/packages/tools/lib/validator/rule-clauses.d.ts.map +1 -0
- package/packages/tools/lib/validator/rule-clauses.js +87 -0
- package/packages/tools/lib/validator/rule-clauses.js.map +1 -0
- package/packages/tools/lib/validator/rule-engine.d.ts +9 -1
- package/packages/tools/lib/validator/rule-engine.d.ts.map +1 -1
- package/packages/tools/lib/validator/rule-engine.js +50 -6
- package/packages/tools/lib/validator/rule-engine.js.map +1 -1
- package/packages/tools/lib/validator/rule-registry.d.ts +4 -8
- package/packages/tools/lib/validator/rule-registry.d.ts.map +1 -1
- package/packages/tools/lib/validator/rule-registry.js +42 -79
- package/packages/tools/lib/validator/rule-registry.js.map +1 -1
- package/packages/tools/lib/validator/rule-tailoring.d.ts +62 -0
- package/packages/tools/lib/validator/rule-tailoring.d.ts.map +1 -0
- package/packages/tools/lib/validator/rule-tailoring.js +85 -0
- package/packages/tools/lib/validator/rule-tailoring.js.map +1 -0
- package/packages/tools/lib/validator/types.d.ts +12 -1
- package/packages/tools/lib/validator/types.d.ts.map +1 -1
- package/packages/tools/lib/validator/workspace-boundary-validator.d.ts +9 -0
- package/packages/tools/lib/validator/workspace-boundary-validator.d.ts.map +1 -0
- package/packages/tools/lib/validator/workspace-boundary-validator.js +28 -0
- package/packages/tools/lib/validator/workspace-boundary-validator.js.map +1 -0
- package/packages/tools/python/memo_model.py +243 -0
- package/packages/tools/python/memo_stage1_syside.py +389 -0
- package/packages/tools/lib/commands/check.d.ts +0 -6
- package/packages/tools/lib/commands/check.d.ts.map +0 -1
- package/packages/tools/lib/commands/check.js +0 -191
- package/packages/tools/lib/commands/check.js.map +0 -1
- package/packages/tools/lib/commands/conformance.d.ts +0 -36
- package/packages/tools/lib/commands/conformance.d.ts.map +0 -1
- package/packages/tools/lib/commands/conformance.js +0 -212
- package/packages/tools/lib/commands/conformance.js.map +0 -1
- package/packages/tools/lib/commands/roundtrip.d.ts +0 -6
- package/packages/tools/lib/commands/roundtrip.d.ts.map +0 -1
- package/packages/tools/lib/commands/roundtrip.js +0 -145
- package/packages/tools/lib/commands/roundtrip.js.map +0 -1
- package/packages/tools/lib/conformance/baseline.d.ts +0 -26
- package/packages/tools/lib/conformance/baseline.d.ts.map +0 -1
- package/packages/tools/lib/conformance/baseline.js +0 -170
- package/packages/tools/lib/conformance/baseline.js.map +0 -1
- package/packages/tools/lib/conformance/bnf.d.ts +0 -84
- package/packages/tools/lib/conformance/bnf.d.ts.map +0 -1
- package/packages/tools/lib/conformance/bnf.js +0 -166
- package/packages/tools/lib/conformance/bnf.js.map +0 -1
- package/packages/tools/lib/conformance/corpus.d.ts +0 -125
- package/packages/tools/lib/conformance/corpus.d.ts.map +0 -1
- package/packages/tools/lib/conformance/corpus.js +0 -190
- package/packages/tools/lib/conformance/corpus.js.map +0 -1
- package/packages/tools/lib/conformance/diff-xmi.d.ts +0 -118
- package/packages/tools/lib/conformance/diff-xmi.d.ts.map +0 -1
- package/packages/tools/lib/conformance/diff-xmi.js +0 -276
- package/packages/tools/lib/conformance/diff-xmi.js.map +0 -1
- package/packages/tools/lib/conformance/generated/syside-rules.d.ts +0 -10
- package/packages/tools/lib/conformance/generated/syside-rules.d.ts.map +0 -1
- package/packages/tools/lib/conformance/generated/syside-rules.js +0 -1142
- package/packages/tools/lib/conformance/generated/syside-rules.js.map +0 -1
- package/packages/tools/lib/conformance/index.d.ts +0 -7
- package/packages/tools/lib/conformance/index.d.ts.map +0 -1
- package/packages/tools/lib/conformance/index.js +0 -19
- package/packages/tools/lib/conformance/index.js.map +0 -1
- package/packages/tools/lib/conformance/run.d.ts +0 -117
- package/packages/tools/lib/conformance/run.d.ts.map +0 -1
- package/packages/tools/lib/conformance/run.js +0 -0
- package/packages/tools/lib/conformance/run.js.map +0 -1
- package/packages/tools/lib/conformance/xmi.d.ts +0 -45
- package/packages/tools/lib/conformance/xmi.d.ts.map +0 -1
- package/packages/tools/lib/conformance/xmi.js +0 -148
- package/packages/tools/lib/conformance/xmi.js.map +0 -1
- package/packages/tools/lib/language/generated/ast.d.ts +0 -3565
- package/packages/tools/lib/language/generated/ast.d.ts.map +0 -1
- package/packages/tools/lib/language/generated/ast.js +0 -2975
- package/packages/tools/lib/language/generated/ast.js.map +0 -1
- package/packages/tools/lib/language/generated/grammar.d.ts +0 -7
- package/packages/tools/lib/language/generated/grammar.d.ts.map +0 -1
- package/packages/tools/lib/language/generated/grammar.js +0 -10643
- package/packages/tools/lib/language/generated/grammar.js.map +0 -1
- package/packages/tools/lib/language/generated/module.d.ts +0 -14
- package/packages/tools/lib/language/generated/module.d.ts.map +0 -1
- package/packages/tools/lib/language/generated/module.js +0 -21
- package/packages/tools/lib/language/generated/module.js.map +0 -1
- package/packages/tools/lib/language/memo-sysml-module.d.ts +0 -24
- package/packages/tools/lib/language/memo-sysml-module.d.ts.map +0 -1
- package/packages/tools/lib/language/memo-sysml-module.js +0 -20
- package/packages/tools/lib/language/memo-sysml-module.js.map +0 -1
- package/packages/tools/lib/model/builder.d.ts +0 -27
- package/packages/tools/lib/model/builder.d.ts.map +0 -1
- package/packages/tools/lib/model/builder.js +0 -2103
- package/packages/tools/lib/model/builder.js.map +0 -1
- package/packages/tools/lib/model/package-registry.d.ts +0 -62
- package/packages/tools/lib/model/package-registry.d.ts.map +0 -1
- package/packages/tools/lib/model/package-registry.js +0 -175
- package/packages/tools/lib/model/package-registry.js.map +0 -1
- package/packages/tools/lib/model/parser-utils.d.ts +0 -65
- package/packages/tools/lib/model/parser-utils.d.ts.map +0 -1
- package/packages/tools/lib/model/parser-utils.js +0 -201
- package/packages/tools/lib/model/parser-utils.js.map +0 -1
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.d.ts +0 -3
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.d.ts.map +0 -1
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.js +0 -97
- package/packages/tools/lib/sysmlc/bin/memo-sysmlc.js.map +0 -1
- package/packages/tools/lib/sysmlc/index.d.ts +0 -2
- package/packages/tools/lib/sysmlc/index.d.ts.map +0 -1
- package/packages/tools/lib/sysmlc/index.js +0 -7
- package/packages/tools/lib/sysmlc/index.js.map +0 -1
- package/packages/tools/lib/sysmlc/server.d.ts +0 -29
- package/packages/tools/lib/sysmlc/server.d.ts.map +0 -1
- package/packages/tools/lib/sysmlc/server.js +0 -168
- package/packages/tools/lib/sysmlc/server.js.map +0 -1
- package/packages/tools/lib/toolchain/lowering.d.ts +0 -63
- package/packages/tools/lib/toolchain/lowering.d.ts.map +0 -1
- package/packages/tools/lib/toolchain/lowering.js +0 -100
- package/packages/tools/lib/toolchain/lowering.js.map +0 -1
- package/packages/tools/lib/toolchain/providers/internal.d.ts +0 -33
- package/packages/tools/lib/toolchain/providers/internal.d.ts.map +0 -1
- package/packages/tools/lib/toolchain/providers/internal.js +0 -286
- package/packages/tools/lib/toolchain/providers/internal.js.map +0 -1
- package/packages/tools/lib/toolchain/sysmlc-client.d.ts +0 -77
- package/packages/tools/lib/toolchain/sysmlc-client.d.ts.map +0 -1
- package/packages/tools/lib/toolchain/sysmlc-client.js +0 -0
- package/packages/tools/lib/toolchain/sysmlc-client.js.map +0 -1
- package/packages/tools/lib/validator/sysml-constraints.d.ts +0 -64
- package/packages/tools/lib/validator/sysml-constraints.d.ts.map +0 -1
- package/packages/tools/lib/validator/sysml-constraints.js +0 -251
- package/packages/tools/lib/validator/sysml-constraints.js.map +0 -1
- package/packages/tools/src/grammar/memo-sysml.langium +0 -1056
|
@@ -1,2103 +0,0 @@
|
|
|
1
|
-
// ─── Model Builder ────────────────────────────────────────────────────────────
|
|
2
|
-
//
|
|
3
|
-
// Walks Langium AST documents and produces a serializable MemoModel.
|
|
4
|
-
// Maps SysML usages → MemoElements and ConnectionUsages → MemoRelationships.
|
|
5
|
-
//
|
|
6
|
-
// Key design decisions:
|
|
7
|
-
// - usage.type (e.g. "Hazard") is matched against config.kinds for layer info
|
|
8
|
-
// - ConnectionUsage.type (e.g. "Mitigates") → lowercase → matches config.relationshipTypes
|
|
9
|
-
// - PackageRegistry tracks cross-file packages and resolves imports
|
|
10
|
-
// - Connections are deferred until all elements are extracted (two-pass)
|
|
11
|
-
// - Doc comments are extracted from usage bodies
|
|
12
|
-
//
|
|
13
|
-
// Dual-mode resolution (M41):
|
|
14
|
-
// - If KindRegistry is provided, it takes precedence over config.kinds
|
|
15
|
-
// - If RelationshipRegistry is provided, it takes precedence for relationship validation
|
|
16
|
-
// - Falls back to config when registries are not provided or entry not found
|
|
17
|
-
// - Backward compatible: existing callers pass no registries, behavior unchanged
|
|
18
|
-
//
|
|
19
|
-
// Phase 5 additions:
|
|
20
|
-
// - ActionDefinition bodies extract parameters (in/out/inout)
|
|
21
|
-
// - ActionUsage supports composite actions with nested actions
|
|
22
|
-
// - FlowConnectionUsage → MemoRelationship of type "flow" with flowItem
|
|
23
|
-
// - SuccessionUsage → MemoRelationship pairs of type "succession"
|
|
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.
|
|
34
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
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';
|
|
38
|
-
// Where an element sits comes from where it was AUTHORED, not from a literal
|
|
39
|
-
// chosen here. See `authoredLayer` below.
|
|
40
|
-
import { resolveLayerFromPath } from './layer-resolver.js';
|
|
41
|
-
import { PackageRegistry } from './package-registry.js';
|
|
42
|
-
import { assignSequentialShortIds, kindToPrefix } from './short-id.js';
|
|
43
|
-
import { identityKey, priorShortIds } from './identity-registry.js';
|
|
44
|
-
import { LANGUAGE_NATIVE_RELATIONS, REFINEMENT_METADATA, pascalToCamelCase } from './relationship-registry.js';
|
|
45
|
-
import { indexKinds, kindConformsTo } from './relationship-legality.js';
|
|
46
|
-
import { CONTROL_KIND_METACLASS } from './activity-notation.js';
|
|
47
|
-
import { toModelType } from './naming.js';
|
|
48
|
-
let relationshipCounter = 0;
|
|
49
|
-
/**
|
|
50
|
-
* Resolve a kind definition using registry-first, config-fallback strategy.
|
|
51
|
-
* Returns the KindDefinition and the resolved kind name.
|
|
52
|
-
*/
|
|
53
|
-
function resolveKindDef(typeName, config, registries) {
|
|
54
|
-
// Try registry first
|
|
55
|
-
if (registries?.kindRegistry) {
|
|
56
|
-
const entry = registries.kindRegistry.getKind(typeName);
|
|
57
|
-
if (entry) {
|
|
58
|
-
return {
|
|
59
|
-
kindDef: { label: entry.label, layer: entry.layer, sysmlConstruct: entry.sysmlConstruct },
|
|
60
|
-
resolvedKind: typeName,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
// Try local part of qualified name
|
|
64
|
-
if (typeName.includes('::')) {
|
|
65
|
-
const localType = typeName.split('::').pop();
|
|
66
|
-
const localEntry = registries.kindRegistry.getKind(localType);
|
|
67
|
-
if (localEntry) {
|
|
68
|
-
return {
|
|
69
|
-
kindDef: { label: localEntry.label, layer: localEntry.layer, sysmlConstruct: localEntry.sysmlConstruct },
|
|
70
|
-
resolvedKind: localType,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// There is no config fallback. Kinds come from the ontology the project
|
|
76
|
-
// resolves; a YAML `kinds:` block used to be able to declare one, which
|
|
77
|
-
// meant a settings file could invent a type the ontology never defined.
|
|
78
|
-
const kinds = {};
|
|
79
|
-
const kindDef = kinds[typeName];
|
|
80
|
-
if (kindDef) {
|
|
81
|
-
return { kindDef, resolvedKind: typeName };
|
|
82
|
-
}
|
|
83
|
-
// Try local part of qualified name in config
|
|
84
|
-
if (typeName.includes('::')) {
|
|
85
|
-
const localType = typeName.split('::').pop();
|
|
86
|
-
if (kinds[localType]) {
|
|
87
|
-
return { kindDef: kinds[localType], resolvedKind: localType };
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return { kindDef: undefined, resolvedKind: typeName };
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Build a MemoModel from parsed documents and config.
|
|
94
|
-
* Optionally accepts registries for dual-mode resolution (registry-first, config-fallback).
|
|
95
|
-
*/
|
|
96
|
-
export function buildMemoModel(documents, config, parseErrors = [], registries) {
|
|
97
|
-
relationshipCounter = 0;
|
|
98
|
-
const elements = new Map();
|
|
99
|
-
const relationships = [];
|
|
100
|
-
const errors = [...parseErrors];
|
|
101
|
-
const deferredConnections = [];
|
|
102
|
-
const deferredFlows = [];
|
|
103
|
-
const deferredSuccessions = [];
|
|
104
|
-
const deferredAllocates = [];
|
|
105
|
-
const deferredBindings = [];
|
|
106
|
-
// Phase 1: Build package registry from all documents
|
|
107
|
-
const registry = new PackageRegistry();
|
|
108
|
-
registry.buildFromDocuments(documents);
|
|
109
|
-
// Phase 2: Extract elements from all documents (populates registry)
|
|
110
|
-
for (const { document, filePath } of documents) {
|
|
111
|
-
const model = document.parseResult.value;
|
|
112
|
-
extractFromModel(model, filePath, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries);
|
|
113
|
-
}
|
|
114
|
-
// Phase 3: Resolve connections using the registry (all elements now known)
|
|
115
|
-
const allElementIds = new Set(elements.keys());
|
|
116
|
-
for (const { conn, filePath, packageName } of deferredConnections) {
|
|
117
|
-
resolveConnection(conn, filePath, packageName, config, elements, relationships, registry, allElementIds);
|
|
118
|
-
}
|
|
119
|
-
// Phase 3b: Resolve flow connections
|
|
120
|
-
for (const { flow, filePath, packageName, parentActionId } of deferredFlows) {
|
|
121
|
-
resolveFlowConnection(flow, filePath, packageName, parentActionId, relationships, allElementIds, elements);
|
|
122
|
-
}
|
|
123
|
-
// Phase 3b2: Resolve port delegations
|
|
124
|
-
for (const { binding, filePath, packageName } of deferredBindings) {
|
|
125
|
-
resolveBinding(binding, filePath, packageName, relationships, allElementIds, elements);
|
|
126
|
-
}
|
|
127
|
-
// Phase 3c: Resolve successions
|
|
128
|
-
for (const { succession, filePath, packageName, parentActionId } of deferredSuccessions) {
|
|
129
|
-
resolveSuccession(succession, filePath, packageName, parentActionId, relationships, allElementIds);
|
|
130
|
-
}
|
|
131
|
-
// Phase 3d: Resolve allocations
|
|
132
|
-
for (const { allocate, filePath, packageName } of deferredAllocates) {
|
|
133
|
-
resolveAllocate(allocate, filePath, packageName, elements, relationships, registry, allElementIds, registries?.relationshipRegistry);
|
|
134
|
-
}
|
|
135
|
-
// Phase 3e: Resolve the native requirement relations. Unlike connections
|
|
136
|
-
// these are not package members — a `satisfy` sits in the body of the part
|
|
137
|
-
// that is the design context, and a `verify` in the body of the case that
|
|
138
|
-
// does the verifying — so they are found by walking containment rather than
|
|
139
|
-
// by the package-member switch, and their context comes from their owner.
|
|
140
|
-
for (const { document, filePath } of documents) {
|
|
141
|
-
resolveNativeTraceUsages(document.parseResult.value, filePath, relationships, registry, allElementIds);
|
|
142
|
-
}
|
|
143
|
-
// Phase 3f: Synthesize containment edges from native nesting. A natively
|
|
144
|
-
// nested part carries its parent in `owner` (set during extraction); MEMO's
|
|
145
|
-
// consumers read containment as a `composes` relationship (parent → child),
|
|
146
|
-
// so emit one per nesting. A model that nests natively then looks identical
|
|
147
|
-
// to one that wrote `Composes`, which is what lets R10-S7 delete the
|
|
148
|
-
// relationship without the containment vanishing. Ports carry `owner` too,
|
|
149
|
-
// so this covers part and item nesting. `state` joined them once nested
|
|
150
|
-
// StateUsage extraction existed to give it something to synthesize from —
|
|
151
|
-
// without a `composes` edge a composite state's substates were exposable
|
|
152
|
-
// (via `owner`) but never rendered nested, since the state-transition
|
|
153
|
-
// template builds its box-in-box layout from COMPOSITION_REL_TYPES, not
|
|
154
|
-
// from `owner` directly.
|
|
155
|
-
const CONTAINING_CONSTRUCTS = new Set(['part', 'item', 'state']);
|
|
156
|
-
for (const el of elements.values()) {
|
|
157
|
-
if (!CONTAINING_CONSTRUCTS.has(el.construct) || !el.owner)
|
|
158
|
-
continue;
|
|
159
|
-
const parent = elements.get(el.owner);
|
|
160
|
-
if (!parent || !CONTAINING_CONSTRUCTS.has(parent.construct))
|
|
161
|
-
continue;
|
|
162
|
-
relationships.push({
|
|
163
|
-
id: `rel-${++relationshipCounter}`,
|
|
164
|
-
type: 'composes',
|
|
165
|
-
sourceId: el.owner,
|
|
166
|
-
sourceEnd: 'parent',
|
|
167
|
-
targetId: el.id,
|
|
168
|
-
targetEnd: 'child',
|
|
169
|
-
file: el.file,
|
|
170
|
-
named: false,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
// A nested action carries its parent in `parentAction` rather than
|
|
174
|
-
// `owner` (the two are set by separate extraction paths), and
|
|
175
|
-
// CR-ONT-065/066 already treat an action-typed end as a legitimate
|
|
176
|
-
// composes participant alongside parts — a functional decomposition
|
|
177
|
-
// (`action fnParent { action fnChild : SystemFunction { ... } }`) needs
|
|
178
|
-
// the same synthesis or a natively nested function tree loses the
|
|
179
|
-
// `composes` edges DSM and traceability consumers read, the exact
|
|
180
|
-
// silent-drop shape R10-S7 exists to close, not open. Every action
|
|
181
|
-
// usage nests some way — a flow step under its flow, a control node
|
|
182
|
-
// under its action — so this is not confined to decomposition the way
|
|
183
|
-
// the part path is; a nested action's owner IS its containing action
|
|
184
|
-
// for every shape the grammar produces, so there is no narrower
|
|
185
|
-
// predicate to gate this on without re-deriving one from AST shape
|
|
186
|
-
// that `parentAction` already erased.
|
|
187
|
-
for (const el of elements.values()) {
|
|
188
|
-
if (el.construct !== 'action' || !el.parentAction)
|
|
189
|
-
continue;
|
|
190
|
-
const parent = elements.get(el.parentAction);
|
|
191
|
-
if (!parent || parent.construct !== 'action')
|
|
192
|
-
continue;
|
|
193
|
-
relationships.push({
|
|
194
|
-
id: `rel-${++relationshipCounter}`,
|
|
195
|
-
type: 'composes',
|
|
196
|
-
sourceId: el.parentAction,
|
|
197
|
-
sourceEnd: 'parent',
|
|
198
|
-
targetId: el.id,
|
|
199
|
-
targetEnd: 'child',
|
|
200
|
-
file: el.file,
|
|
201
|
-
named: false,
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
// Keep ownership of a declaration separate from ownership of the type that
|
|
205
|
-
// classifies it. A project usage of `Hazard` is editable project content;
|
|
206
|
-
// its classifier is a read-only ontology definition.
|
|
207
|
-
applySemanticProvenance(elements, relationships, registries);
|
|
208
|
-
// Build indexes
|
|
209
|
-
const elementsByKind = new Map();
|
|
210
|
-
const elementsByLayer = new Map();
|
|
211
|
-
for (const el of elements.values()) {
|
|
212
|
-
if (!elementsByKind.has(el.kind))
|
|
213
|
-
elementsByKind.set(el.kind, []);
|
|
214
|
-
elementsByKind.get(el.kind).push(el);
|
|
215
|
-
if (!elementsByLayer.has(el.layer))
|
|
216
|
-
elementsByLayer.set(el.layer, []);
|
|
217
|
-
elementsByLayer.get(el.layer).push(el);
|
|
218
|
-
}
|
|
219
|
-
// Assign each three-letter prefix one sequential display index. This is
|
|
220
|
-
// deliberately distinct from the technical UUID assigned below.
|
|
221
|
-
const elementsByPrefix = new Map();
|
|
222
|
-
for (const element of elements.values()) {
|
|
223
|
-
const prefix = kindToPrefix(element.kind);
|
|
224
|
-
const prefixElements = elementsByPrefix.get(prefix) ?? [];
|
|
225
|
-
prefixElements.push(element);
|
|
226
|
-
elementsByPrefix.set(prefix, prefixElements);
|
|
227
|
-
}
|
|
228
|
-
// Identities assigned on earlier builds win. Both of these are quoted
|
|
229
|
-
// outside the model, so recomputing them from current content — which is
|
|
230
|
-
// what happened before `memo.identity.yaml` — silently repointed every
|
|
231
|
-
// external reference whenever a file moved or an element was inserted.
|
|
232
|
-
const priorIdentities = config.priorIdentities ?? {};
|
|
233
|
-
const priorShortIdsByElement = priorShortIds(priorIdentities);
|
|
234
|
-
for (const [prefix, prefixElements] of elementsByPrefix) {
|
|
235
|
-
const idToShortId = assignSequentialShortIds(prefix, prefixElements.map(e => e.id), priorShortIdsByElement);
|
|
236
|
-
for (const el of prefixElements) {
|
|
237
|
-
el.shortId = idToShortId.get(el.id);
|
|
238
|
-
// `uuid` is part of the ontology's identification core, so a model
|
|
239
|
-
// may author it. An authored value wins: it is the whole point of
|
|
240
|
-
// writing one — the element keeps its identity across a file move
|
|
241
|
-
// or an id change, which the derived hash cannot survive.
|
|
242
|
-
// Precedence: an authored uuid, then the one this project already
|
|
243
|
-
// assigned, then a fresh derivation. The middle term is what makes a
|
|
244
|
-
// uuid survive a file move — the derivation hashes the file path, so
|
|
245
|
-
// without it the same element gets a new identity when it moves.
|
|
246
|
-
el.uuid = el.attributes.uuid?.trim()
|
|
247
|
-
|| priorIdentities[identityKey(el)]?.uuid
|
|
248
|
-
|| stableElementUuid(el);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
// Phase 4: Validate relationship end types (warnings only).
|
|
252
|
-
// A kind conforms to an end type if it equals it or specializes it
|
|
253
|
-
// (transitively) — e.g. HardwareAssembly conforms to MemoPart.
|
|
254
|
-
if (registries?.relationshipRegistry) {
|
|
255
|
-
// Same resolver the authoring UI and the server persistence path use,
|
|
256
|
-
// so a link the panel offers is a link the builder accepts.
|
|
257
|
-
const kindIndex = indexKinds(registries.kindRegistry?.toDefinitionDTOs() ?? []);
|
|
258
|
-
// A project definition specializes an ontology kind, and the ontology
|
|
259
|
-
// registry has never heard of it: `AfferaStakeholder` is declared in
|
|
260
|
-
// this project, not in memo. So a chain like
|
|
261
|
-
// `AfferaHospitalEpLabStakeholder :> AfferaStakeholder :> MemoPart`
|
|
262
|
-
// broke at the first hop and fell through to guessing by name suffix,
|
|
263
|
-
// reporting a well-formed context diagram as malformed.
|
|
264
|
-
//
|
|
265
|
-
// A definition element records what it specializes in its own `kind`,
|
|
266
|
-
// so the model supplies the missing links. This is the same walk the
|
|
267
|
-
// explorer makes to file an element under its ontology kind.
|
|
268
|
-
const projectSuper = new Map();
|
|
269
|
-
for (const el of elements.values()) {
|
|
270
|
-
if (!el.isDefinition || !el.kind || el.kind === el.name)
|
|
271
|
-
continue;
|
|
272
|
-
if (!projectSuper.has(el.name))
|
|
273
|
-
projectSuper.set(el.name, el.kind);
|
|
274
|
-
if (el.id !== el.name && !projectSuper.has(el.id))
|
|
275
|
-
projectSuper.set(el.id, el.kind);
|
|
276
|
-
}
|
|
277
|
-
const conformsTo = (kind, expected) => {
|
|
278
|
-
let current = kind;
|
|
279
|
-
const seen = new Set();
|
|
280
|
-
while (current && !seen.has(current)) {
|
|
281
|
-
if (current === expected)
|
|
282
|
-
return true;
|
|
283
|
-
if (kindConformsTo(current, expected, kindIndex))
|
|
284
|
-
return true;
|
|
285
|
-
seen.add(current);
|
|
286
|
-
current = kindIndex.get(current)?.superType ?? projectSuper.get(current);
|
|
287
|
-
}
|
|
288
|
-
// Legacy fallback when neither the ontology nor the project knows
|
|
289
|
-
// this kind's hierarchy at all.
|
|
290
|
-
return !kindIndex.has(kind) && !projectSuper.has(kind) && kind.endsWith(expected);
|
|
291
|
-
};
|
|
292
|
-
for (const rel of relationships) {
|
|
293
|
-
const regEntry = registries.relationshipRegistry.getRelType(rel.type);
|
|
294
|
-
if (!regEntry || regEntry.ends.length === 0)
|
|
295
|
-
continue;
|
|
296
|
-
const sourceEl = elements.get(rel.sourceId);
|
|
297
|
-
const targetEl = elements.get(rel.targetId);
|
|
298
|
-
// Check if the source/target kinds match the typed ends
|
|
299
|
-
for (const end of regEntry.ends) {
|
|
300
|
-
if (!end.type)
|
|
301
|
-
continue; // untyped ends allow any kind
|
|
302
|
-
// Match end to source or target by position (first end = source, second = target)
|
|
303
|
-
const endIndex = regEntry.ends.indexOf(end);
|
|
304
|
-
const el = endIndex === 0 ? sourceEl : targetEl;
|
|
305
|
-
if (!el)
|
|
306
|
-
continue;
|
|
307
|
-
if (!conformsTo(el.kind, end.type)) {
|
|
308
|
-
errors.push({
|
|
309
|
-
message: `[well-formedness] Relationship "${rel.type}" expects ${end.name} to be ${end.type}, but found ${el.kind}`,
|
|
310
|
-
file: rel.file ?? '',
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
const relationshipsByType = new Map();
|
|
317
|
-
const outgoing = new Map();
|
|
318
|
-
const incoming = new Map();
|
|
319
|
-
for (const rel of relationships) {
|
|
320
|
-
if (!relationshipsByType.has(rel.type))
|
|
321
|
-
relationshipsByType.set(rel.type, []);
|
|
322
|
-
relationshipsByType.get(rel.type).push(rel);
|
|
323
|
-
if (!outgoing.has(rel.sourceId))
|
|
324
|
-
outgoing.set(rel.sourceId, []);
|
|
325
|
-
outgoing.get(rel.sourceId).push(rel);
|
|
326
|
-
if (!incoming.has(rel.targetId))
|
|
327
|
-
incoming.set(rel.targetId, []);
|
|
328
|
-
incoming.get(rel.targetId).push(rel);
|
|
329
|
-
}
|
|
330
|
-
// A local definition has already resolved its own ontology kind; usages
|
|
331
|
-
// typed by it inherit that kind, including through a local definition chain.
|
|
332
|
-
if (registries?.kindRegistry) {
|
|
333
|
-
const byName = new Map();
|
|
334
|
-
for (const [id, el] of elements) {
|
|
335
|
-
if (!byName.has(id))
|
|
336
|
-
byName.set(id, el);
|
|
337
|
-
if (el.name && !byName.has(el.name))
|
|
338
|
-
byName.set(el.name, el);
|
|
339
|
-
}
|
|
340
|
-
const known = (kind) => Boolean(registries.kindRegistry?.getKind(kind));
|
|
341
|
-
for (let pass = 0; pass < 16; pass++) {
|
|
342
|
-
let progressed = false;
|
|
343
|
-
for (const el of elements.values()) {
|
|
344
|
-
if (!el.kind || known(el.kind))
|
|
345
|
-
continue;
|
|
346
|
-
const def = byName.get(el.kind.split('::').pop());
|
|
347
|
-
if (def && def !== el && def.kind && def.kind !== el.kind) {
|
|
348
|
-
el.kind = def.kind;
|
|
349
|
-
if (def.layer && (!el.layer || el.layer === 'unknown'))
|
|
350
|
-
el.layer = def.layer;
|
|
351
|
-
progressed = true;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
if (!progressed)
|
|
355
|
-
break;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
const unresolvedReferences = [];
|
|
359
|
-
const reachableCache = new Map();
|
|
360
|
-
const reachableNames = (packageName, seen = new Set()) => {
|
|
361
|
-
if (seen.has(packageName))
|
|
362
|
-
return new Set();
|
|
363
|
-
seen.add(packageName);
|
|
364
|
-
const pkg = registry.getPackage(packageName);
|
|
365
|
-
if (!pkg)
|
|
366
|
-
return new Set();
|
|
367
|
-
const names = new Set(pkg.elementIds);
|
|
368
|
-
for (const imported of pkg.imports) {
|
|
369
|
-
if (imported.isWildcard) {
|
|
370
|
-
for (const name of reachableNames(imported.packageName, seen))
|
|
371
|
-
names.add(name);
|
|
372
|
-
}
|
|
373
|
-
else if (imported.namedImport)
|
|
374
|
-
names.add(imported.namedImport);
|
|
375
|
-
}
|
|
376
|
-
return names;
|
|
377
|
-
};
|
|
378
|
-
for (const [elementId, el] of elements) {
|
|
379
|
-
for (const [key, value] of Object.entries(el.attributes)) {
|
|
380
|
-
if (!key.endsWith('Type') || !value.includes('::'))
|
|
381
|
-
continue;
|
|
382
|
-
const parts = value.split('::');
|
|
383
|
-
const leaf = parts.pop().split('.')[0];
|
|
384
|
-
const packageName = parts.join('::');
|
|
385
|
-
if (!registry.getPackage(packageName))
|
|
386
|
-
continue;
|
|
387
|
-
const names = reachableCache.get(packageName) ?? reachableNames(packageName);
|
|
388
|
-
reachableCache.set(packageName, names);
|
|
389
|
-
if (!names.has(leaf)) {
|
|
390
|
-
unresolvedReferences.push({ elementId, elementName: el.name ?? elementId,
|
|
391
|
-
elementKind: el.kind ?? 'Element', reference: value, packageName,
|
|
392
|
-
missingName: leaf, file: el.file ?? '' });
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
return {
|
|
397
|
-
elements,
|
|
398
|
-
relationships,
|
|
399
|
-
errors,
|
|
400
|
-
packages: collectPackages(registry),
|
|
401
|
-
unresolvedReferences,
|
|
402
|
-
elementsByKind,
|
|
403
|
-
elementsByLayer,
|
|
404
|
-
relationshipsByType,
|
|
405
|
-
outgoing,
|
|
406
|
-
incoming,
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* The declared packages, in the shape the model carries them.
|
|
411
|
-
*
|
|
412
|
-
* Read from the registry rather than from element membership so a package that
|
|
413
|
-
* declares nothing is still reported: an explorer builds its containment tree
|
|
414
|
-
* from this list, and a newly created package has no members yet by definition.
|
|
415
|
-
*/
|
|
416
|
-
function collectPackages(registry) {
|
|
417
|
-
const packages = [];
|
|
418
|
-
for (const entry of registry.getPackages().values()) {
|
|
419
|
-
const separator = entry.qualifiedName.lastIndexOf('::');
|
|
420
|
-
packages.push({
|
|
421
|
-
qualifiedName: entry.qualifiedName,
|
|
422
|
-
name: separator === -1 ? entry.qualifiedName : entry.qualifiedName.slice(separator + 2),
|
|
423
|
-
...(separator === -1 ? {} : { parent: entry.qualifiedName.slice(0, separator) }),
|
|
424
|
-
file: entry.file,
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
return packages.sort((a, b) => a.qualifiedName.localeCompare(b.qualifiedName));
|
|
428
|
-
}
|
|
429
|
-
function applySemanticProvenance(elements, relationships, registries) {
|
|
430
|
-
const table = registries?.provenance;
|
|
431
|
-
if (!table)
|
|
432
|
-
return;
|
|
433
|
-
const entryFor = (kind) => registries?.kindRegistry?.getKind(kind)
|
|
434
|
-
?? registries?.kindRegistry?.getKind(kind.split('::').pop() ?? kind);
|
|
435
|
-
const classifierFor = (kind) => {
|
|
436
|
-
const entry = entryFor(kind);
|
|
437
|
-
if (!entry?.qualifiedName)
|
|
438
|
-
return undefined;
|
|
439
|
-
return {
|
|
440
|
-
qualifiedName: entry.qualifiedName,
|
|
441
|
-
shortName: entry.name,
|
|
442
|
-
provenance: entry.sourceFile ? table.lookup(entry.sourceFile) : undefined,
|
|
443
|
-
};
|
|
444
|
-
};
|
|
445
|
-
const classifierChainFor = (kind) => {
|
|
446
|
-
const chain = [];
|
|
447
|
-
const seen = new Set();
|
|
448
|
-
let entry = entryFor(kind);
|
|
449
|
-
while (entry?.qualifiedName && !seen.has(entry.qualifiedName)) {
|
|
450
|
-
seen.add(entry.qualifiedName);
|
|
451
|
-
chain.push({
|
|
452
|
-
qualifiedName: entry.qualifiedName,
|
|
453
|
-
shortName: entry.name,
|
|
454
|
-
provenance: entry.sourceFile ? table.lookup(entry.sourceFile) : undefined,
|
|
455
|
-
});
|
|
456
|
-
entry = entry.superType ? entryFor(entry.superType) : undefined;
|
|
457
|
-
}
|
|
458
|
-
return chain.length > 0 ? chain : undefined;
|
|
459
|
-
};
|
|
460
|
-
const declarationFor = (file, kind) => ({
|
|
461
|
-
declaration: table.lookupOrProject(file),
|
|
462
|
-
classifier: kind ? classifierFor(kind) : undefined,
|
|
463
|
-
classifierChain: kind ? classifierChainFor(kind) : undefined,
|
|
464
|
-
});
|
|
465
|
-
for (const element of elements.values()) {
|
|
466
|
-
element.provenance = declarationFor(element.file, element.kind);
|
|
467
|
-
}
|
|
468
|
-
for (const relationship of relationships) {
|
|
469
|
-
relationship.provenance = declarationFor(relationship.file, relationship.type);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
/**
|
|
473
|
-
* Derive a UUID from source identity, rather than allocating a random value on
|
|
474
|
-
* every compilation. This is the machine identity; `shortId` is the compact
|
|
475
|
-
* human-facing PREFIX-1, PREFIX-2, … label used in explorers.
|
|
476
|
-
*/
|
|
477
|
-
function stableElementUuid(element) {
|
|
478
|
-
const bytes = createHash('sha256')
|
|
479
|
-
.update(`${element.file}\0${element.kind}\0${element.id}`)
|
|
480
|
-
.digest()
|
|
481
|
-
.subarray(0, 16);
|
|
482
|
-
bytes[6] = (bytes[6] & 0x0f) | 0x50; // UUID v5 shape
|
|
483
|
-
bytes[8] = (bytes[8] & 0x3f) | 0x80; // RFC 4122 variant
|
|
484
|
-
const hex = bytes.toString('hex');
|
|
485
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
486
|
-
}
|
|
487
|
-
// ─── AST Walking ────────────────────────────────────────────────────────────
|
|
488
|
-
function extractFromModel(model, filePath, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries) {
|
|
489
|
-
for (const member of model.members) {
|
|
490
|
-
if (member.$type === 'PackageDeclaration') {
|
|
491
|
-
extractFromPackage(member, filePath, '', config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
/**
|
|
496
|
-
* Display label for a package rendered as a folder: an explicit `Matrix folder:`
|
|
497
|
-
* line in the package's doc comment wins; otherwise the package name with a
|
|
498
|
-
* `folder_` prefix stripped and underscores spaced.
|
|
499
|
-
*/
|
|
500
|
-
function packageFolderDisplayName(pkg) {
|
|
501
|
-
const doc = extractDocComment(pkg.members);
|
|
502
|
-
if (doc) {
|
|
503
|
-
const match = doc.match(/Matrix folder:\s*(.+)/);
|
|
504
|
-
if (match)
|
|
505
|
-
return match[1].trim();
|
|
506
|
-
}
|
|
507
|
-
return pkg.name.replace(/^folder_/, '').replace(/_/g, ' ');
|
|
508
|
-
}
|
|
509
|
-
/** Tag a usage with the folder its owning package presents, so panels can group
|
|
510
|
-
* by nested SysML package folders. */
|
|
511
|
-
function tagUsagePackageFolder(element, folderLabel) {
|
|
512
|
-
if (!element || !folderLabel)
|
|
513
|
-
return;
|
|
514
|
-
element.attributes['elementPackage'] = folderLabel;
|
|
515
|
-
}
|
|
516
|
-
function extractFromPackage(pkg, filePath, parentPackage, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries) {
|
|
517
|
-
const packageName = parentPackage ? `${parentPackage}::${pkg.name}` : pkg.name;
|
|
518
|
-
// Only nested packages present as folders; a top-level package is the tree
|
|
519
|
-
// root, not a folder within it.
|
|
520
|
-
const folderLabel = parentPackage ? packageFolderDisplayName(pkg) : undefined;
|
|
521
|
-
for (const member of pkg.members) {
|
|
522
|
-
switch (member.$type) {
|
|
523
|
-
case 'PackageDeclaration':
|
|
524
|
-
extractFromPackage(member, filePath, packageName, config, elements, deferredConnections, deferredFlows, deferredSuccessions, deferredAllocates, deferredBindings, errors, registry, registries);
|
|
525
|
-
break;
|
|
526
|
-
case 'PartUsage':
|
|
527
|
-
extractUsage(member, 'part', filePath, packageName, config, elements, registry, registries);
|
|
528
|
-
tagUsagePackageFolder(elements.get(member.name), folderLabel);
|
|
529
|
-
break;
|
|
530
|
-
case 'RequirementUsage':
|
|
531
|
-
extractUsage(member, 'requirement', filePath, packageName, config, elements, registry, registries);
|
|
532
|
-
tagUsagePackageFolder(elements.get(member.name), folderLabel);
|
|
533
|
-
break;
|
|
534
|
-
case 'ItemUsage':
|
|
535
|
-
extractUsage(member, 'item', filePath, packageName, config, elements, registry, registries);
|
|
536
|
-
tagUsagePackageFolder(elements.get(member.name), folderLabel);
|
|
537
|
-
break;
|
|
538
|
-
case 'UseCaseDeclaration': {
|
|
539
|
-
const useCase = member;
|
|
540
|
-
if (useCase.isDefinition) {
|
|
541
|
-
extractDefinitionElement({ name: useCase.name, specialization: useCase.specialization, body: useCase.body ?? useCase.usageBody }, 'use case', filePath, packageName, config, elements, registry, registries);
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
544
|
-
extractUsage({ name: useCase.name, type: useCase.type, body: useCase.usageBody }, 'use case', filePath, packageName, config, elements, registry, registries);
|
|
545
|
-
}
|
|
546
|
-
break;
|
|
547
|
-
}
|
|
548
|
-
case 'VerificationUsage':
|
|
549
|
-
extractUsage(member, 'verification', filePath, packageName, config, elements, registry, registries);
|
|
550
|
-
tagUsagePackageFolder(elements.get(member.name), folderLabel);
|
|
551
|
-
break;
|
|
552
|
-
case 'StateUsage':
|
|
553
|
-
extractUsage(member, 'state', filePath, packageName, config, elements, registry, registries);
|
|
554
|
-
break;
|
|
555
|
-
case 'InterfaceUsage':
|
|
556
|
-
extractUsage(member, 'interface', filePath, packageName, config, elements, registry, registries);
|
|
557
|
-
break;
|
|
558
|
-
case 'ActionUsage':
|
|
559
|
-
extractActionUsage(member, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries);
|
|
560
|
-
break;
|
|
561
|
-
case 'PortUsage':
|
|
562
|
-
extractUsage(member, 'port', filePath, packageName, config, elements, registry, registries);
|
|
563
|
-
break;
|
|
564
|
-
case 'ViewUsage':
|
|
565
|
-
extractUsage(member, 'view', filePath, packageName, config, elements, registry, registries);
|
|
566
|
-
break;
|
|
567
|
-
case 'ViewpointUsage':
|
|
568
|
-
extractViewpointUsage(member, filePath, packageName, config, elements, registry, registries);
|
|
569
|
-
break;
|
|
570
|
-
case 'ConnectionUsage':
|
|
571
|
-
// Defer connection resolution until all elements are extracted
|
|
572
|
-
deferredConnections.push({
|
|
573
|
-
conn: member,
|
|
574
|
-
filePath,
|
|
575
|
-
packageName,
|
|
576
|
-
});
|
|
577
|
-
break;
|
|
578
|
-
case 'BindingUsage':
|
|
579
|
-
// Port delegation. Deferred for the same reason as flows: both
|
|
580
|
-
// ends are dotted paths that only resolve once every nested
|
|
581
|
-
// port is an element.
|
|
582
|
-
deferredBindings.push({
|
|
583
|
-
binding: member,
|
|
584
|
-
filePath,
|
|
585
|
-
packageName,
|
|
586
|
-
});
|
|
587
|
-
break;
|
|
588
|
-
case 'FlowConnectionUsage':
|
|
589
|
-
// A flow between two action usages declared side by side in a
|
|
590
|
-
// package has no enclosing action, so parentActionId is unset
|
|
591
|
-
// and the endpoints resolve against the package scope.
|
|
592
|
-
deferredFlows.push({
|
|
593
|
-
flow: member,
|
|
594
|
-
filePath,
|
|
595
|
-
packageName,
|
|
596
|
-
});
|
|
597
|
-
break;
|
|
598
|
-
case 'MessageUsage':
|
|
599
|
-
// `Message : FlowUsage`: native messages deliberately lower
|
|
600
|
-
// through the same path as MEMO's flow-shaped compatibility
|
|
601
|
-
// vocabulary, so consumers retain one trace-edge spelling.
|
|
602
|
-
deferredFlows.push({
|
|
603
|
-
flow: member,
|
|
604
|
-
filePath,
|
|
605
|
-
packageName,
|
|
606
|
-
});
|
|
607
|
-
break;
|
|
608
|
-
case 'SuccessionUsage':
|
|
609
|
-
deferredSuccessions.push({
|
|
610
|
-
succession: member,
|
|
611
|
-
filePath,
|
|
612
|
-
packageName,
|
|
613
|
-
});
|
|
614
|
-
break;
|
|
615
|
-
case 'AllocateUsage':
|
|
616
|
-
deferredAllocates.push({
|
|
617
|
-
allocate: member,
|
|
618
|
-
filePath,
|
|
619
|
-
packageName,
|
|
620
|
-
});
|
|
621
|
-
break;
|
|
622
|
-
// ─── Native declarations (plan §8) ──────────────────────────
|
|
623
|
-
//
|
|
624
|
-
// `actor u : User;`, `stakeholder s : Stakeholder;` and
|
|
625
|
-
// `concern c : Concern;` declare the same elements `part u : User;`
|
|
626
|
-
// declares — same id, same kind, same attributes, same doc. Only
|
|
627
|
-
// the metaclass differs, and the metaclass is what makes them
|
|
628
|
-
// legible to a conforming tool. Routing them through extractUsage
|
|
629
|
-
// is what keeps the migration in step 3 a spelling change rather
|
|
630
|
-
// than a content change.
|
|
631
|
-
case 'ActorMember':
|
|
632
|
-
extractUsage(member, 'actor', filePath, packageName, config, elements, registry, registries);
|
|
633
|
-
break;
|
|
634
|
-
case 'StakeholderMember':
|
|
635
|
-
extractUsage(member, 'stakeholder', filePath, packageName, config, elements, registry, registries);
|
|
636
|
-
break;
|
|
637
|
-
case 'ConcernUsage':
|
|
638
|
-
extractUsage(member, 'concern', filePath, packageName, config, elements, registry, registries);
|
|
639
|
-
break;
|
|
640
|
-
case 'TransitionUsage':
|
|
641
|
-
extractTransition(member, filePath, packageName, config, elements, registry, registries);
|
|
642
|
-
break;
|
|
643
|
-
// ─── Definition members ─────────────────────────────────────
|
|
644
|
-
case 'ActionDefinition':
|
|
645
|
-
extractActionDefinition(member, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries);
|
|
646
|
-
break;
|
|
647
|
-
case 'ItemDefinition':
|
|
648
|
-
extractItemDefinition(member, filePath, packageName, config, elements, registry, registries);
|
|
649
|
-
break;
|
|
650
|
-
case 'PartDefinition':
|
|
651
|
-
case 'PortDefinition':
|
|
652
|
-
case 'InterfaceDefinition':
|
|
653
|
-
case 'ConnectionDefinition':
|
|
654
|
-
extractDefinitionElement(member, DEFINITION_CONSTRUCTS[member.$type], filePath, packageName, config, elements, registry, registries);
|
|
655
|
-
extractDefinitionPorts(member, filePath, packageName, config, elements, registry, registries);
|
|
656
|
-
// A definition's body is composition: `part def Pump { part
|
|
657
|
-
// motor : Motor; }` is what a BDD draws and what an IBD looks
|
|
658
|
-
// inside. Nested usages become elements owned by the
|
|
659
|
-
// definition, exactly as they do under a part usage.
|
|
660
|
-
extractNestedParts(member, filePath, packageName, config, elements, registry, registries);
|
|
661
|
-
break;
|
|
662
|
-
case 'RequirementDefinition':
|
|
663
|
-
case 'VerificationDefinition':
|
|
664
|
-
case 'StateDefinition':
|
|
665
|
-
case 'AttributeDefinition':
|
|
666
|
-
case 'EnumDefinition':
|
|
667
|
-
extractDefinitionElement(member, DEFINITION_CONSTRUCTS[member.$type], filePath, packageName, config, elements, registry, registries);
|
|
668
|
-
break;
|
|
669
|
-
// A `view def` / `viewpoint def` stays out: those are presentation
|
|
670
|
-
// apparatus, read through the viewpoint tree rather than as model
|
|
671
|
-
// content.
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
function extractUsage(usage, construct, filePath, packageName, config, elements, registry, registries) {
|
|
676
|
-
const id = usage.name;
|
|
677
|
-
const typeName = usage.type; // e.g. "Hazard", "Requirement"
|
|
678
|
-
// Dual-mode resolution: registry first, then config fallback
|
|
679
|
-
const { kindDef: finalKindDef, resolvedKind } = typeName
|
|
680
|
-
? resolveKindDef(typeName, config, registries)
|
|
681
|
-
: { kindDef: undefined, resolvedKind: 'Unknown' };
|
|
682
|
-
const attributes = extractAttributes(usage.body);
|
|
683
|
-
if (typeName)
|
|
684
|
-
attributes.usageType = typeName;
|
|
685
|
-
const doc = extractDocComment(usage.body);
|
|
686
|
-
// A view's `expose <path>;` members declare its element membership
|
|
687
|
-
// natively — SysML v2's own visibility mechanism, in place of the MEMO
|
|
688
|
-
// `IncludedIn` relationship. Collected as a comma-separated attribute so
|
|
689
|
-
// `resolveViewElementIds` in view-deriver.ts can resolve each path
|
|
690
|
-
// against the model the same way it resolves `selectionQuery.*`.
|
|
691
|
-
if (construct === 'view') {
|
|
692
|
-
const exposePaths = (usage.body || [])
|
|
693
|
-
.filter(member => member.$type === 'ExposeMember')
|
|
694
|
-
.map(member => member.path);
|
|
695
|
-
if (exposePaths.length > 0) {
|
|
696
|
-
attributes['expose'] = exposePaths.join(',');
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
// Nested part/reference members that are view METADATA, not containment:
|
|
700
|
-
// bindings (`part/ref viewpoint :> vp;`) and the `:>>` redefinition of an
|
|
701
|
-
// inherited feature whose body is attributes (`part :>> selectionQuery
|
|
702
|
-
// { ... }`). These are flattened onto the owner as plain / prefixed
|
|
703
|
-
// attributes so SysML-modelled views expose their viewpoint binding and
|
|
704
|
-
// selection-query metadata to consumers. A typed nested part is NOT metadata
|
|
705
|
-
// — it is real containment and is extracted as its own element below.
|
|
706
|
-
for (const member of usage.body || []) {
|
|
707
|
-
if (member.$type !== 'PartMember' && member.$type !== 'RefMember')
|
|
708
|
-
continue;
|
|
709
|
-
const pm = member;
|
|
710
|
-
if (pm.boundRef && pm.name) {
|
|
711
|
-
// Two shapes land here. `part/ref viewpointDefinition :> vp;` names
|
|
712
|
-
// the feature in `name` and the value in `boundRef`. The subsetting
|
|
713
|
-
// form for a multi-valued feature —
|
|
714
|
-
// `part/ref vpLogical :> viewpointDefinition = someViewpoint;` — puts
|
|
715
|
-
// the FEATURE in `boundRef` and the value in `subsetValue`, and its
|
|
716
|
-
// member name is arbitrary. Attribute it to the feature it subsets,
|
|
717
|
-
// or a view governed by three viewpoints would surface as three
|
|
718
|
-
// unrelated attributes nothing reads.
|
|
719
|
-
const key = pm.subsetValue ? pm.boundRef : pm.name;
|
|
720
|
-
const value = pm.subsetValue ?? pm.boundRef;
|
|
721
|
-
// A feature with multiplicity may be rebound more than once. Keep
|
|
722
|
-
// every binding as a comma-separated value so view conformance can
|
|
723
|
-
// model one view against several viewpoints without cloning it.
|
|
724
|
-
const previous = attributes[key];
|
|
725
|
-
attributes[key] = previous ? `${previous},${value}` : value;
|
|
726
|
-
}
|
|
727
|
-
else if (!pm.type && pm.body && pm.name) {
|
|
728
|
-
// R10-S3 guard: an UNTYPED nested part with an attribute body is
|
|
729
|
-
// view metadata — the `part :>> selectionQuery { ... }` (or the
|
|
730
|
-
// un-redefined `part selectionQuery { ... }`) that view derivation
|
|
731
|
-
// reads as `selectionQuery.*` attributes. It carries no kind, so it
|
|
732
|
-
// is not a contained element. Flatten it; a TYPED nested part
|
|
733
|
-
// (`part valve : Valve`) is real containment and is extracted below.
|
|
734
|
-
const nested = extractAttributes(pm.body);
|
|
735
|
-
for (const [k, v] of Object.entries(nested)) {
|
|
736
|
-
attributes[`${pm.name}.${k}`] = v;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
// Human-readable name: prefer "attribute redefines name" over usage name
|
|
741
|
-
const displayName = attributes['name'] || attributes['title'] || id;
|
|
742
|
-
const element = {
|
|
743
|
-
id,
|
|
744
|
-
name: displayName,
|
|
745
|
-
kind: resolvedKind,
|
|
746
|
-
construct,
|
|
747
|
-
layer: finalKindDef?.layer || 'unknown',
|
|
748
|
-
file: filePath,
|
|
749
|
-
package: packageName || undefined,
|
|
750
|
-
attributes,
|
|
751
|
-
doc,
|
|
752
|
-
};
|
|
753
|
-
// Port-specific fields
|
|
754
|
-
if (construct === 'port') {
|
|
755
|
-
const portNode = usage;
|
|
756
|
-
const directedItems = (usage.body || [])
|
|
757
|
-
.filter(member => member.$type === 'ItemUsage' && !!member.direction)
|
|
758
|
-
.map(member => member);
|
|
759
|
-
const itemDirections = new Set(directedItems.map(item => item.direction));
|
|
760
|
-
element.portSpec = {
|
|
761
|
-
type: portNode.type,
|
|
762
|
-
direction: (portNode.direction ?? (itemDirections.size === 1 ? directedItems[0]?.direction : undefined)),
|
|
763
|
-
isConjugated: portNode.isConjugated ?? false,
|
|
764
|
-
};
|
|
765
|
-
element.parameters = directedItems
|
|
766
|
-
.map(feature => {
|
|
767
|
-
return {
|
|
768
|
-
name: feature.name,
|
|
769
|
-
direction: feature.direction,
|
|
770
|
-
type: feature.type || 'Item',
|
|
771
|
-
};
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
elements.set(id, element);
|
|
775
|
-
registry.registerElement(id, packageName);
|
|
776
|
-
// A port's body may declare further ports. Recurse only after the parent is
|
|
777
|
-
// in the map, so the child's `owner` points at an element that exists.
|
|
778
|
-
if (construct === 'port') {
|
|
779
|
-
extractDefinitionPorts(usage, filePath, packageName, config, elements, registry, registries);
|
|
780
|
-
}
|
|
781
|
-
// A part's body may nest further parts. SysML v2 expresses containment by
|
|
782
|
-
// nesting; MEMO historically expressed it with a `Composes` connection, and
|
|
783
|
-
// the two must yield the same model. Extract each nested part as its own
|
|
784
|
-
// element with `owner` set — exactly as a nested port is — only after the
|
|
785
|
-
// parent is in the map. buildMemoModel synthesizes the `composes` edge from
|
|
786
|
-
// the resulting `owner` chain.
|
|
787
|
-
//
|
|
788
|
-
// A part usage may also declare its OWN boundary ports directly in its
|
|
789
|
-
// body (`part x : T { in port p : DataPort; }`), distinct from a nested
|
|
790
|
-
// part's ports and from any ports the type `T` declares at the def level
|
|
791
|
-
// (that path is `extractDefinitionPorts` at package scope, line ~668).
|
|
792
|
-
// Without this, an inline-authored port silently has no element: it
|
|
793
|
-
// parses, every relationship endpoint referencing it resolves to a
|
|
794
|
-
// dangling id, and nothing downstream reports why.
|
|
795
|
-
// Items nest too — a standard contains its clauses — so the nested-usage
|
|
796
|
-
// walk runs for both. Ports stay part-only: an item has no boundary.
|
|
797
|
-
if (construct === 'part' || construct === 'item') {
|
|
798
|
-
extractNestedParts(usage, filePath, packageName, config, elements, registry, registries);
|
|
799
|
-
}
|
|
800
|
-
if (construct === 'part') {
|
|
801
|
-
extractDefinitionPorts(usage, filePath, packageName, config, elements, registry, registries);
|
|
802
|
-
}
|
|
803
|
-
// A native `transition` lives inside the state machine that owns it, which
|
|
804
|
-
// is where the language puts it and where MEMO's `part def Transition`
|
|
805
|
-
// never could. Extract it from the state usage's body so the two spellings
|
|
806
|
-
// yield the same element set.
|
|
807
|
-
//
|
|
808
|
-
// A native `state` nests the same way — `state infusing { state priming;
|
|
809
|
-
// state delivering; }` is how a composite state declares its substates —
|
|
810
|
-
// but nothing walked a state usage's body for further StateUsage members
|
|
811
|
-
// at all. It parsed, `extractUsage` above created the ONE element for the
|
|
812
|
-
// state doing the nesting, and every substate silently became nothing: no
|
|
813
|
-
// element, so `expose pumpModes::**` (which walks `owner` chains) found
|
|
814
|
-
// only the state machine itself, and every state-transition view of a
|
|
815
|
-
// composite state rendered as a single unexpanded box. This is the
|
|
816
|
-
// `extractNestedParts` recursion for state usages, inlined here rather
|
|
817
|
-
// than as its own function because the transition loop it joins already
|
|
818
|
-
// walks the same body: `extractUsage(..., 'state', ...)` on a nested state
|
|
819
|
-
// re-enters this same function, so a third level (priming inside infusing
|
|
820
|
-
// inside pumpModes) reaches this loop again on its own.
|
|
821
|
-
for (const member of usage.body || []) {
|
|
822
|
-
const m = member;
|
|
823
|
-
if (m.$type === 'TransitionUsage') {
|
|
824
|
-
extractTransition(m, filePath, packageName, config, elements, registry, registries);
|
|
825
|
-
const transitionEl = elements.get(m.name);
|
|
826
|
-
if (transitionEl)
|
|
827
|
-
transitionEl.owner = id;
|
|
828
|
-
}
|
|
829
|
-
else if (construct === 'state' && m.$type === 'StateUsage') {
|
|
830
|
-
extractUsage(m, 'state', filePath, packageName, config, elements, registry, registries);
|
|
831
|
-
const childEl = elements.get(m.name);
|
|
832
|
-
if (childEl)
|
|
833
|
-
childEl.owner = id;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
/**
|
|
838
|
-
* Extract a native `transition` as a MemoElement.
|
|
839
|
-
*
|
|
840
|
-
* MEMO models a transition as `part def Transition` with `sourceState` and
|
|
841
|
-
* `targetState` as **Strings** (§13.3) — and in the shipped content those
|
|
842
|
-
* strings hold display names ("Idle"), not element ids, so nothing can follow
|
|
843
|
-
* them to the states they name. The native form's source and target are real
|
|
844
|
-
* references, so they are resolved to element ids here.
|
|
845
|
-
*
|
|
846
|
-
* Both are still written into the attribute map under the same keys the part
|
|
847
|
-
* def declares. That is deliberate: it keeps every existing consumer of
|
|
848
|
-
* `sourceState` / `targetState` working while the two spellings coexist, and it
|
|
849
|
-
* is what makes the eventual migration a change of value (display name →
|
|
850
|
-
* element id) that a diff can show, rather than a change of shape that it
|
|
851
|
-
* cannot.
|
|
852
|
-
*
|
|
853
|
-
* An anonymous transition (`transition initial then off;`) declares no element.
|
|
854
|
-
* It is a control statement, not a named thing the model traces to.
|
|
855
|
-
*/
|
|
856
|
-
function extractTransition(transition, filePath, packageName, config, elements, registry, registries) {
|
|
857
|
-
if (!transition.name)
|
|
858
|
-
return;
|
|
859
|
-
const attributes = {
|
|
860
|
-
...extractAttributes(transition.body),
|
|
861
|
-
sourceState: transition.source,
|
|
862
|
-
targetState: transition.target,
|
|
863
|
-
};
|
|
864
|
-
if (transition.trigger)
|
|
865
|
-
attributes.trigger = transition.trigger;
|
|
866
|
-
if (transition.effect)
|
|
867
|
-
attributes.effectSummary = transition.effect;
|
|
868
|
-
const guard = renderGuardExpression(transition.guard);
|
|
869
|
-
if (guard !== undefined)
|
|
870
|
-
attributes.guardSummary = guard;
|
|
871
|
-
const { kindDef, resolvedKind } = transition.type
|
|
872
|
-
? resolveKindDef(transition.type, config, registries)
|
|
873
|
-
: { kindDef: undefined, resolvedKind: 'Unknown' };
|
|
874
|
-
elements.set(transition.name, {
|
|
875
|
-
id: transition.name,
|
|
876
|
-
name: attributes.name || transition.name,
|
|
877
|
-
kind: resolvedKind,
|
|
878
|
-
construct: 'transition',
|
|
879
|
-
layer: kindDef?.layer || 'unknown',
|
|
880
|
-
file: filePath,
|
|
881
|
-
package: packageName || undefined,
|
|
882
|
-
attributes,
|
|
883
|
-
doc: extractDocComment(transition.body),
|
|
884
|
-
});
|
|
885
|
-
registry.registerElement(transition.name, packageName);
|
|
886
|
-
}
|
|
887
|
-
/**
|
|
888
|
-
* Extract an ActionDefinition as a MemoElement with parameters.
|
|
889
|
-
*/
|
|
890
|
-
function extractActionDefinition(actionDef, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries) {
|
|
891
|
-
const id = actionDef.name;
|
|
892
|
-
// Extract parameters from body
|
|
893
|
-
const parameters = [];
|
|
894
|
-
const bodyMembers = actionDef.body || [];
|
|
895
|
-
for (const member of bodyMembers) {
|
|
896
|
-
if (member.$type === 'ActionParameterMember' || (member.$type === 'ItemUsage' && member.direction)) {
|
|
897
|
-
const param = member;
|
|
898
|
-
parameters.push({
|
|
899
|
-
name: param.name,
|
|
900
|
-
direction: param.direction,
|
|
901
|
-
type: param.type || 'Item',
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
const attributes = extractAttributes(bodyMembers);
|
|
906
|
-
const doc = extractDocComment(bodyMembers);
|
|
907
|
-
const behaviorKind = actionDef.behaviorKind ?? 'action';
|
|
908
|
-
// `action def AcquireSensorData :> FunctionalAction` defines a
|
|
909
|
-
// FunctionalAction. Stamping it `ActionDefinition` named the SysML
|
|
910
|
-
// METACLASS as though it were a MEMO kind — the ontology declares no such
|
|
911
|
-
// kind, so every project action def landed in the explorer's "not in
|
|
912
|
-
// ontology" bucket, and a validator had to look it up by that literal.
|
|
913
|
-
// The metaclass is what `construct` and `isDefinition` say; the kind is
|
|
914
|
-
// what the definition specializes.
|
|
915
|
-
const superType = actionDef.specialization?.superType;
|
|
916
|
-
const resolved = superType ? resolveKindDef(superType, config, registries) : undefined;
|
|
917
|
-
const ontologyKind = resolved?.kindDef && resolved.kindDef.layer && resolved.kindDef.layer !== 'unknown'
|
|
918
|
-
? resolved
|
|
919
|
-
: undefined;
|
|
920
|
-
const element = {
|
|
921
|
-
id,
|
|
922
|
-
name: id,
|
|
923
|
-
// Only where nothing resolves does the metaclass stand in, and there it
|
|
924
|
-
// is the truthful answer: this is a SysML ActionDefinition and nothing
|
|
925
|
-
// more is known about it.
|
|
926
|
-
kind: ontologyKind?.resolvedKind
|
|
927
|
-
?? (behaviorKind === 'operator' ? 'OperatorDefinition'
|
|
928
|
-
: behaviorKind === 'function' ? 'FunctionDefinition' : 'ActionDefinition'),
|
|
929
|
-
construct: 'action',
|
|
930
|
-
isDefinition: true,
|
|
931
|
-
layer: ontologyKind?.kindDef?.layer ?? authoredLayer(filePath),
|
|
932
|
-
file: filePath,
|
|
933
|
-
package: packageName || undefined,
|
|
934
|
-
attributes: { ...attributes, behaviorKind },
|
|
935
|
-
doc,
|
|
936
|
-
parameters: parameters.length > 0 ? parameters : undefined,
|
|
937
|
-
};
|
|
938
|
-
elements.set(id, element);
|
|
939
|
-
registry.registerElement(id, packageName);
|
|
940
|
-
// Standard SysML activity bodies may contain action/control usages directly
|
|
941
|
-
// (not wrapped in an ActionUsage). Preserve those declarations so a valid
|
|
942
|
-
// activity diagram cannot collapse to its enclosing action alone.
|
|
943
|
-
// `previousStep` carries the member a `then` refers back to: in standard
|
|
944
|
-
// SysML a body member written `then action x ...` succeeds the step declared
|
|
945
|
-
// before it, with no `succession` usage naming either end.
|
|
946
|
-
let previousStep;
|
|
947
|
-
let terminateCount = 0;
|
|
948
|
-
for (const member of bodyMembers) {
|
|
949
|
-
let step;
|
|
950
|
-
if (member.$type === 'ActionUsage') {
|
|
951
|
-
extractActionUsage(member, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries, id);
|
|
952
|
-
step = member.name;
|
|
953
|
-
}
|
|
954
|
-
else if (member.$type === 'ControlNodeUsage') {
|
|
955
|
-
extractControlNode(member, filePath, packageName, elements, registry, id);
|
|
956
|
-
step = member.name;
|
|
957
|
-
}
|
|
958
|
-
else if (['AcceptActionUsage', 'SendActionUsage', 'DecisionNodeUsage', 'MergeNodeUsage', 'TerminateUsage'].includes(member.$type)) {
|
|
959
|
-
const node = member;
|
|
960
|
-
// A terminate node has no name to be given one by, and an id keyed
|
|
961
|
-
// on `elements.size` moves whenever anything else in the file does.
|
|
962
|
-
// Key it on the action that owns it instead, so a view can name it
|
|
963
|
-
// and a saved layout keeps pointing at the same node.
|
|
964
|
-
const fallback = node.$type === 'TerminateUsage'
|
|
965
|
-
? `${id}__terminate${terminateCount++ === 0 ? '' : terminateCount}`
|
|
966
|
-
: `${node.$type}-${elements.size}`;
|
|
967
|
-
const nodeId = node.name ?? fallback;
|
|
968
|
-
step = nodeId;
|
|
969
|
-
extractStandardActivityNode(node, filePath, packageName, elements, registry, id, nodeId);
|
|
970
|
-
}
|
|
971
|
-
else if (member.$type === 'SuccessionUsage') {
|
|
972
|
-
deferredSuccessions.push({ succession: member, filePath, packageName, parentActionId: id });
|
|
973
|
-
}
|
|
974
|
-
if (step && member.followsPrevious && previousStep) {
|
|
975
|
-
deferredSuccessions.push({
|
|
976
|
-
succession: { steps: [{ ref: previousStep }, { ref: step }] },
|
|
977
|
-
filePath,
|
|
978
|
-
packageName,
|
|
979
|
-
parentActionId: id,
|
|
980
|
-
});
|
|
981
|
-
}
|
|
982
|
-
if (step)
|
|
983
|
-
previousStep = step;
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
function extractStandardActivityNode(node, filePath, packageName, elements, registry, parentActionId, id) {
|
|
987
|
-
const typeToKind = {
|
|
988
|
-
AcceptActionUsage: 'AcceptActionUsage', SendActionUsage: 'SendActionUsage',
|
|
989
|
-
DecisionNodeUsage: 'DecisionNodeUsage', MergeNodeUsage: 'MergeNodeUsage', TerminateUsage: 'ActivityFinalNodeUsage',
|
|
990
|
-
};
|
|
991
|
-
const parameters = node.$type === 'AcceptActionUsage' && node.payloadName
|
|
992
|
-
? [{ name: node.payloadName, direction: 'out', type: node.payloadType ?? 'Item' }]
|
|
993
|
-
: undefined;
|
|
994
|
-
elements.set(id, {
|
|
995
|
-
id, name: node.name ?? node.$type, kind: typeToKind[node.$type] ?? node.$type,
|
|
996
|
-
construct: 'action', layer: authoredLayer(filePath), file: filePath, package: packageName || undefined,
|
|
997
|
-
attributes: { ...(node.payloadName ? { payloadName: node.payloadName } : {}), ...(node.payloadType ? { payloadType: node.payloadType } : {}) }, parentAction: parentActionId, parameters,
|
|
998
|
-
});
|
|
999
|
-
registry.registerElement(id, packageName);
|
|
1000
|
-
}
|
|
1001
|
-
/**
|
|
1002
|
-
* Extract an ItemDefinition as a MemoElement.
|
|
1003
|
-
*/
|
|
1004
|
-
function extractItemDefinition(itemDef, filePath, packageName, config, elements, registry, registries) {
|
|
1005
|
-
const id = itemDef.name;
|
|
1006
|
-
const attributes = extractAttributes(itemDef.body);
|
|
1007
|
-
const doc = extractDocComment(itemDef.body);
|
|
1008
|
-
const typeName = itemDef.specialization?.superType;
|
|
1009
|
-
const { kindDef, resolvedKind } = typeName
|
|
1010
|
-
? resolveKindDef(typeName, config, registries)
|
|
1011
|
-
: { kindDef: undefined, resolvedKind: 'ItemDefinition' };
|
|
1012
|
-
const element = {
|
|
1013
|
-
id,
|
|
1014
|
-
name: id,
|
|
1015
|
-
kind: kindDef?.layer && kindDef.layer !== 'unknown' ? resolvedKind : 'ItemDefinition',
|
|
1016
|
-
construct: 'item',
|
|
1017
|
-
isDefinition: true,
|
|
1018
|
-
layer: kindDef?.layer && kindDef.layer !== 'unknown' ? kindDef.layer : authoredLayer(filePath),
|
|
1019
|
-
file: filePath,
|
|
1020
|
-
package: packageName || undefined,
|
|
1021
|
-
attributes,
|
|
1022
|
-
doc,
|
|
1023
|
-
};
|
|
1024
|
-
elements.set(id, element);
|
|
1025
|
-
registry.registerElement(id, packageName);
|
|
1026
|
-
}
|
|
1027
|
-
/**
|
|
1028
|
-
* Walk an owner's body to extract port usages as owned port elements.
|
|
1029
|
-
* Sets owner on ports and ownedPorts on the owner.
|
|
1030
|
-
*
|
|
1031
|
-
* The owner may be a definition (`part def Board { port p : DataPort; }`) or a
|
|
1032
|
-
* USAGE — including another port. SysML v2 nests ports inside ports, which is
|
|
1033
|
-
* how a panel cluster says "this one boundary feature carries these three
|
|
1034
|
-
* connectors". Without the usage case a model that nests natively simply loses
|
|
1035
|
-
* the children: they are declared, they resolve, and they never become
|
|
1036
|
-
* elements, so they vanish from every diagram and every count. The only
|
|
1037
|
-
* alternative spelling is a `Composes` connection from a port to a port, which
|
|
1038
|
-
* CR-ONT-065 forbids — a whole in a decomposition has to be a part, an action
|
|
1039
|
-
* or a state. So the native form was the only correct one, and it was the one
|
|
1040
|
-
* that did not work.
|
|
1041
|
-
*/
|
|
1042
|
-
/**
|
|
1043
|
-
* The SysML construct each definition declares, in the spelling its usages
|
|
1044
|
-
* carry — a `part def` and a `part` are the same construct, one defining and
|
|
1045
|
-
* one using.
|
|
1046
|
-
*/
|
|
1047
|
-
const DEFINITION_CONSTRUCTS = {
|
|
1048
|
-
PartDefinition: 'part',
|
|
1049
|
-
PortDefinition: 'port',
|
|
1050
|
-
InterfaceDefinition: 'interface',
|
|
1051
|
-
ConnectionDefinition: 'connection',
|
|
1052
|
-
RequirementDefinition: 'requirement',
|
|
1053
|
-
VerificationDefinition: 'verification',
|
|
1054
|
-
StateDefinition: 'state',
|
|
1055
|
-
AttributeDefinition: 'attribute',
|
|
1056
|
-
EnumDefinition: 'enumeration',
|
|
1057
|
-
};
|
|
1058
|
-
/**
|
|
1059
|
-
* A definition the PROJECT declares, as a model element.
|
|
1060
|
-
*
|
|
1061
|
-
* `part def Pump :> LogicalComponent` defines a Pump. It was registered as a
|
|
1062
|
-
* kind and nothing else, so no view could select it and no BDD or IBD could
|
|
1063
|
-
* draw it — which is most of what a definition is for. It is an element now,
|
|
1064
|
-
* and its usages read beneath it: a usage's `kind` is the definition's name,
|
|
1065
|
-
* which is the link every explorer already follows.
|
|
1066
|
-
*
|
|
1067
|
-
* The kind it carries is the ONTOLOGY kind it specializes, so a view, a
|
|
1068
|
-
* viewpoint filter and a palette that admit `LogicalComponent` admit the
|
|
1069
|
-
* definition of one without being edited. `isDefinition` is what tells the two
|
|
1070
|
-
* apart afterwards — a definition is a type, not an instance of one, and
|
|
1071
|
-
* anything counting instances must say so.
|
|
1072
|
-
*
|
|
1073
|
-
* This is only ever project content: the ontology's own definitions are read
|
|
1074
|
-
* by the kind registry and are never parsed into the model.
|
|
1075
|
-
*/
|
|
1076
|
-
function extractDefinitionElement(definition, construct, filePath, packageName, config, elements, registry, registries) {
|
|
1077
|
-
const id = definition.name;
|
|
1078
|
-
if (!id || elements.has(id))
|
|
1079
|
-
return;
|
|
1080
|
-
// A `library package` is how a project writes ontology-style content: its
|
|
1081
|
-
// definitions are types for other models to use, not this model's content.
|
|
1082
|
-
// The user's distinction exactly — model definitions become elements,
|
|
1083
|
-
// library ones stay kinds, which is what they already were.
|
|
1084
|
-
if (registry.isLibraryPackage(packageName))
|
|
1085
|
-
return;
|
|
1086
|
-
const superType = definition.specialization?.superType;
|
|
1087
|
-
const { kindDef, resolvedKind } = superType
|
|
1088
|
-
? resolveKindDef(superType, config, registries)
|
|
1089
|
-
: { kindDef: undefined, resolvedKind: undefined };
|
|
1090
|
-
const attributes = extractAttributes(definition.body ?? []);
|
|
1091
|
-
const doc = extractDocComment(definition.body ?? []);
|
|
1092
|
-
elements.set(id, {
|
|
1093
|
-
id,
|
|
1094
|
-
name: attributes['name'] || attributes['title'] || id,
|
|
1095
|
-
// A definition that specializes nothing the ontology knows is still a
|
|
1096
|
-
// definition; it says so rather than borrowing a kind it has not got.
|
|
1097
|
-
kind: resolvedKind ?? `${construct.charAt(0).toUpperCase()}${construct.slice(1)}Definition`,
|
|
1098
|
-
construct,
|
|
1099
|
-
layer: kindDef?.layer || 'unknown',
|
|
1100
|
-
file: filePath,
|
|
1101
|
-
package: packageName || undefined,
|
|
1102
|
-
attributes,
|
|
1103
|
-
doc,
|
|
1104
|
-
isDefinition: true,
|
|
1105
|
-
});
|
|
1106
|
-
registry.registerElement(id, packageName);
|
|
1107
|
-
}
|
|
1108
|
-
function extractDefinitionPorts(def, filePath, packageName, config, elements, registry, registries) {
|
|
1109
|
-
const ownerId = def.name;
|
|
1110
|
-
const body = def.body || [];
|
|
1111
|
-
const ownedPortIds = [];
|
|
1112
|
-
for (const member of body) {
|
|
1113
|
-
if (member.$type === 'PortUsage') {
|
|
1114
|
-
const portUsage = member;
|
|
1115
|
-
extractUsage(portUsage, 'port', filePath, packageName, config, elements, registry, registries);
|
|
1116
|
-
const portEl = elements.get(portUsage.name);
|
|
1117
|
-
if (portEl) {
|
|
1118
|
-
portEl.owner = ownerId;
|
|
1119
|
-
ownedPortIds.push(portUsage.name);
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
if (ownedPortIds.length > 0) {
|
|
1124
|
-
const ownerEl = elements.get(ownerId);
|
|
1125
|
-
if (ownerEl) {
|
|
1126
|
-
ownerEl.ownedPorts = ownedPortIds;
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
/**
|
|
1131
|
-
* Walk a usage's body to extract nested parts AND items as owned elements,
|
|
1132
|
-
* setting `owner` on each child.
|
|
1133
|
-
*
|
|
1134
|
-
* `extractUsage` flattens the `PartMember` shapes that are view metadata — a
|
|
1135
|
-
* reference binding (`part viewpoint :> vp;`) and an untyped body
|
|
1136
|
-
* (`part :>> selectionQuery { ... }`). A TYPED nested part
|
|
1137
|
-
* (`part valve : Valve { ... }`) is real containment: without this it is
|
|
1138
|
-
* declared, resolves, and never becomes an element — the same silent drop
|
|
1139
|
-
* nested ports had before `extractDefinitionPorts` walked port usages. The
|
|
1140
|
-
* `composes` edge that makes containment legible to consumers is synthesized
|
|
1141
|
-
* from the `owner` chain in buildMemoModel.
|
|
1142
|
-
*/
|
|
1143
|
-
function extractNestedParts(owner, filePath, packageName, config, elements, registry, registries) {
|
|
1144
|
-
const ownerId = owner.name;
|
|
1145
|
-
for (const member of owner.body || []) {
|
|
1146
|
-
const pm = member;
|
|
1147
|
-
const isPart = pm.$type === 'PartMember';
|
|
1148
|
-
// A nested ITEM is containment too — `item iec62304 { item clause4 …}`
|
|
1149
|
-
// is how every standard declares its clauses. Without this branch the
|
|
1150
|
-
// child parses cleanly in both parsers and never becomes an element at
|
|
1151
|
-
// all: not a missing edge, a missing element. That is the
|
|
1152
|
-
// BindingUsage / ExposeMember / untyped-flow shape again.
|
|
1153
|
-
//
|
|
1154
|
-
// A DIRECTED item is excluded: `in item payload : BubbleSignal;` is a
|
|
1155
|
-
// port's payload parameter, not something the port contains. The same
|
|
1156
|
-
// `direction` test already separates the two at the action-parameter
|
|
1157
|
-
// and flow sites.
|
|
1158
|
-
const isItem = pm.$type === 'ItemUsage' && !pm.direction;
|
|
1159
|
-
if (!isPart && !isItem)
|
|
1160
|
-
continue;
|
|
1161
|
-
// Only a TYPED nested usage is containment. Untyped bodies (view
|
|
1162
|
-
// selectionQuery) and reference bindings are view metadata, flattened
|
|
1163
|
-
// to attributes in extractUsage — skip them here or a view's metadata
|
|
1164
|
-
// becomes a phantom element and its selection query is lost.
|
|
1165
|
-
if (!pm.type || pm.boundRef || !pm.name)
|
|
1166
|
-
continue;
|
|
1167
|
-
extractUsage({ name: pm.name, type: pm.type, body: pm.body }, isPart ? 'part' : 'item', filePath, packageName, config, elements, registry, registries);
|
|
1168
|
-
const childEl = elements.get(pm.name);
|
|
1169
|
-
if (childEl)
|
|
1170
|
-
childEl.owner = ownerId;
|
|
1171
|
-
}
|
|
1172
|
-
extractNestedPackages(owner, filePath, packageName, config, elements, registry, registries);
|
|
1173
|
-
}
|
|
1174
|
-
/**
|
|
1175
|
-
* A `package` nested inside a usage body — `part scrHome : UIElement { package
|
|
1176
|
-
* grpHeader { part btnBack : UIElement; } }`.
|
|
1177
|
-
*
|
|
1178
|
-
* A package GROUPS; it does not decompose. So the group becomes an element (the
|
|
1179
|
-
* explorer needs a node to render, and the user asked to create these to
|
|
1180
|
-
* organise a screen or a leaf of the model), but the things inside it stay
|
|
1181
|
-
* contained by the OWNER — putting them under the package would assert a part
|
|
1182
|
-
* decomposition the author did not write, and would make the containment
|
|
1183
|
-
* family rules see a package "containing" software.
|
|
1184
|
-
*
|
|
1185
|
-
* Without this the package and everything in it parses in both parsers and
|
|
1186
|
-
* never becomes an element: the BindingUsage / ExposeMember / nested-item shape
|
|
1187
|
-
* for the fourth time.
|
|
1188
|
-
*/
|
|
1189
|
-
function extractNestedPackages(owner, filePath, packageName, config, elements, registry, registries) {
|
|
1190
|
-
for (const member of owner.body || []) {
|
|
1191
|
-
const pm = member;
|
|
1192
|
-
if (pm.$type !== 'PackageDeclaration' || !pm.name)
|
|
1193
|
-
continue;
|
|
1194
|
-
elements.set(pm.name, {
|
|
1195
|
-
id: pm.name,
|
|
1196
|
-
name: pm.name,
|
|
1197
|
-
kind: ELEMENT_PACKAGE_KIND,
|
|
1198
|
-
construct: 'package',
|
|
1199
|
-
layer: elements.get(owner.name)?.layer ?? 'unknown',
|
|
1200
|
-
file: filePath,
|
|
1201
|
-
package: packageName,
|
|
1202
|
-
attributes: {},
|
|
1203
|
-
owner: owner.name,
|
|
1204
|
-
});
|
|
1205
|
-
for (const grouped of pm.members ?? []) {
|
|
1206
|
-
const gm = grouped;
|
|
1207
|
-
// `part btnBack : UIElement;` parses as a PartMember and
|
|
1208
|
-
// `part btnBack : UIElement { … }` as a PartUsage — the same
|
|
1209
|
-
// declaration with and without a body. Accepting only the first
|
|
1210
|
-
// dropped every grouped element that declares anything, which is
|
|
1211
|
-
// most of them.
|
|
1212
|
-
const isPart = gm.$type === 'PartMember' || gm.$type === 'PartUsage';
|
|
1213
|
-
const isItem = gm.$type === 'ItemUsage' && !gm.direction;
|
|
1214
|
-
if (!isPart && !isItem)
|
|
1215
|
-
continue;
|
|
1216
|
-
if (!gm.type || gm.boundRef || !gm.name)
|
|
1217
|
-
continue;
|
|
1218
|
-
extractUsage({ name: gm.name, type: gm.type, body: gm.body }, isPart ? 'part' : 'item', filePath, packageName, config, elements, registry, registries);
|
|
1219
|
-
const childEl = elements.get(gm.name);
|
|
1220
|
-
if (childEl) {
|
|
1221
|
-
// Contained by the OWNER; the package only labels the grouping.
|
|
1222
|
-
childEl.owner = owner.name;
|
|
1223
|
-
childEl.attributes['elementPackage'] = pm.name;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
/** The kind a nested grouping package becomes, distinct from a namespace package. */
|
|
1229
|
-
export const ELEMENT_PACKAGE_KIND = 'ElementPackage';
|
|
1230
|
-
/**
|
|
1231
|
-
* A `viewpoint` usage, and any viewpoint declared inside it.
|
|
1232
|
-
*
|
|
1233
|
-
* A viewpoint nests for system-of-systems modelling: the viewpoint that frames
|
|
1234
|
-
* the whole system of systems declares one viewpoint per constituent system,
|
|
1235
|
-
* which is how ISO 42010 composes a description of a description. Native SysML
|
|
1236
|
-
* already permits it (`ViewpointUsage` is a `UsageBodyMember`) and the grammar
|
|
1237
|
-
* already parsed it — nothing extracted it, so a nested viewpoint became no
|
|
1238
|
-
* element at all and every consumer saw one flat list.
|
|
1239
|
-
*
|
|
1240
|
-
* The nested viewpoint carries its parent in `owner`, the same way a nested
|
|
1241
|
-
* part does. Unlike a part, no `composes` edge is synthesized: a viewpoint is
|
|
1242
|
-
* not a `part` construct, and framing is not containment of hardware.
|
|
1243
|
-
*/
|
|
1244
|
-
function extractViewpointUsage(usage, filePath, packageName, config, elements, registry, registries, ownerId) {
|
|
1245
|
-
if (!usage.name)
|
|
1246
|
-
return;
|
|
1247
|
-
extractUsage({ name: usage.name, type: usage.type, body: usage.body }, 'viewpoint', filePath, packageName, config, elements, registry, registries);
|
|
1248
|
-
const element = elements.get(usage.name);
|
|
1249
|
-
if (element && ownerId)
|
|
1250
|
-
element.owner = ownerId;
|
|
1251
|
-
for (const member of usage.body || []) {
|
|
1252
|
-
const nested = member;
|
|
1253
|
-
if (nested.$type !== 'ViewpointUsage')
|
|
1254
|
-
continue;
|
|
1255
|
-
extractViewpointUsage(nested, filePath, packageName, config, elements, registry, registries, usage.name);
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
/**
|
|
1259
|
-
* The layer an element belongs to when its type resolves to no ontology kind.
|
|
1260
|
-
*
|
|
1261
|
-
* This used to be the literal `'behavior'`, in five places. It was invented
|
|
1262
|
-
* here — the ontology has no behavior layer, and nothing checked the string
|
|
1263
|
-
* against the vocabulary the ontology produces — and it was wrong about the
|
|
1264
|
-
* model besides: all 440 of one project's `ItemDefinition`s are authored under
|
|
1265
|
-
* `architecture/implementation/` and were reported as behavior regardless.
|
|
1266
|
-
*
|
|
1267
|
-
* MEMO keeps namespace and folder path aligned, so the directory an element is
|
|
1268
|
-
* authored in already states where it belongs, and `resolveLayerFromPath` is
|
|
1269
|
-
* the same derivation used for the ontology's own kinds. A file the convention
|
|
1270
|
-
* does not cover still yields `unknown`, which is the honest answer and is
|
|
1271
|
-
* reported as one downstream rather than dressed as a layer.
|
|
1272
|
-
*/
|
|
1273
|
-
function authoredLayer(filePath) {
|
|
1274
|
-
return resolveLayerFromPath(filePath);
|
|
1275
|
-
}
|
|
1276
|
-
/**
|
|
1277
|
-
* Extract an ActionUsage, including nested actions, flows, and successions.
|
|
1278
|
-
* Supports both typed (action name : Type;) and composite (action name { ... }) forms.
|
|
1279
|
-
*/
|
|
1280
|
-
function extractActionUsage(usage, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries, parentActionId) {
|
|
1281
|
-
const id = usage.name;
|
|
1282
|
-
const typeName = usage.type;
|
|
1283
|
-
// Dual-mode resolution: registry first, then config fallback. A type
|
|
1284
|
-
// that resolves without a real layer is a model-local action def, not an
|
|
1285
|
-
// ontology kind — the usage stays an ActionUsage on the behavior layer
|
|
1286
|
-
// (the def reference is kept in the actionType attribute below).
|
|
1287
|
-
const behaviorKind = usage.behaviorKind ?? 'action';
|
|
1288
|
-
let kind = behaviorKind === 'operator' ? 'OperatorUsage'
|
|
1289
|
-
: behaviorKind === 'function' ? 'FunctionUsage' : 'ActionUsage';
|
|
1290
|
-
let layer = authoredLayer(filePath);
|
|
1291
|
-
if (typeName) {
|
|
1292
|
-
const { kindDef, resolvedKind } = resolveKindDef(typeName, config, registries);
|
|
1293
|
-
if (kindDef && kindDef.layer && kindDef.layer !== 'unknown') {
|
|
1294
|
-
kind = resolvedKind;
|
|
1295
|
-
layer = kindDef.layer;
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
const bodyMembers = usage.body || [];
|
|
1299
|
-
const attributes = extractAttributes(bodyMembers);
|
|
1300
|
-
attributes['behaviorKind'] = behaviorKind;
|
|
1301
|
-
const doc = extractDocComment(bodyMembers);
|
|
1302
|
-
const displayName = attributes['name'] || attributes['title'] || id;
|
|
1303
|
-
// SysML types a usage the same way whatever the usage is — `part p : Board`
|
|
1304
|
-
// and `action a : CoordinateWorkflows` are one mechanism — so the type goes
|
|
1305
|
-
// in `usageType`, the field every other usage already uses. Recording it
|
|
1306
|
-
// only under `actionType` meant anything reading typing generically saw
|
|
1307
|
-
// parts typed and actions untyped, and a BDD of the function hierarchy
|
|
1308
|
-
// resolved none of its definitions.
|
|
1309
|
-
//
|
|
1310
|
-
// `actionType` stays for flow type checking, which reads it by name.
|
|
1311
|
-
if (typeName) {
|
|
1312
|
-
attributes['actionType'] = typeName;
|
|
1313
|
-
attributes['usageType'] = typeName;
|
|
1314
|
-
}
|
|
1315
|
-
const element = {
|
|
1316
|
-
id,
|
|
1317
|
-
name: displayName,
|
|
1318
|
-
kind,
|
|
1319
|
-
construct: 'action',
|
|
1320
|
-
layer,
|
|
1321
|
-
file: filePath,
|
|
1322
|
-
package: packageName || undefined,
|
|
1323
|
-
attributes,
|
|
1324
|
-
doc,
|
|
1325
|
-
parentAction: parentActionId,
|
|
1326
|
-
parameters: bodyMembers
|
|
1327
|
-
.filter(member => member.$type === 'ActionParameterMember')
|
|
1328
|
-
.map(member => ({ name: member.name, direction: member.direction, type: member.type || 'Item' })),
|
|
1329
|
-
};
|
|
1330
|
-
elements.set(id, element);
|
|
1331
|
-
registry.registerElement(id, packageName);
|
|
1332
|
-
// Walk body for nested behavior members
|
|
1333
|
-
for (const member of bodyMembers) {
|
|
1334
|
-
switch (member.$type) {
|
|
1335
|
-
case 'ActionUsage':
|
|
1336
|
-
// Nested action usage — recursive extraction
|
|
1337
|
-
extractActionUsage(member, filePath, packageName, config, elements, deferredFlows, deferredSuccessions, registry, registries, id);
|
|
1338
|
-
break;
|
|
1339
|
-
case 'FlowConnectionUsage':
|
|
1340
|
-
deferredFlows.push({
|
|
1341
|
-
flow: member,
|
|
1342
|
-
filePath,
|
|
1343
|
-
packageName,
|
|
1344
|
-
parentActionId: id,
|
|
1345
|
-
});
|
|
1346
|
-
break;
|
|
1347
|
-
case 'SuccessionUsage':
|
|
1348
|
-
deferredSuccessions.push({
|
|
1349
|
-
succession: member,
|
|
1350
|
-
filePath,
|
|
1351
|
-
packageName,
|
|
1352
|
-
parentActionId: id,
|
|
1353
|
-
});
|
|
1354
|
-
break;
|
|
1355
|
-
case 'ControlNodeUsage':
|
|
1356
|
-
extractControlNode(member, filePath, packageName, elements, registry, id);
|
|
1357
|
-
break;
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
/**
|
|
1362
|
-
* Extract a control node. Modeled as a behavior-layer element with
|
|
1363
|
-
* `construct: 'action'` so it participates in succession ordering and swimlane
|
|
1364
|
-
* layout like any other flow step, but carries the metaclass its `controlKind`
|
|
1365
|
-
* names and a `controlKind` attribute, so renderers draw the right symbol —
|
|
1366
|
-
* a bar for fork/join, a diamond for decide/merge.
|
|
1367
|
-
*
|
|
1368
|
-
* The kind comes from `CONTROL_KIND_METACLASS`, the same binding
|
|
1369
|
-
* `activityNodeType` classifies by; a second mapping here is how `decide` and
|
|
1370
|
-
* `merge` came to be stored as `JoinNode`.
|
|
1371
|
-
*/
|
|
1372
|
-
function extractControlNode(node, filePath, packageName, elements, registry, parentActionId) {
|
|
1373
|
-
const id = node.name;
|
|
1374
|
-
const kind = CONTROL_KIND_METACLASS[node.controlKind];
|
|
1375
|
-
elements.set(id, {
|
|
1376
|
-
id,
|
|
1377
|
-
name: node.name,
|
|
1378
|
-
kind,
|
|
1379
|
-
construct: 'action',
|
|
1380
|
-
layer: authoredLayer(filePath),
|
|
1381
|
-
file: filePath,
|
|
1382
|
-
package: packageName || undefined,
|
|
1383
|
-
attributes: { controlKind: node.controlKind },
|
|
1384
|
-
parentAction: parentActionId,
|
|
1385
|
-
});
|
|
1386
|
-
registry.registerElement(id, packageName);
|
|
1387
|
-
}
|
|
1388
|
-
function resolveConnection(conn, filePath, packageName, config, elements, relationships, registry, allElementIds) {
|
|
1389
|
-
const typeName = conn.type; // e.g. "Mitigates", "TraceTo"
|
|
1390
|
-
if (!conn.source || !conn.target)
|
|
1391
|
-
return;
|
|
1392
|
-
// An untyped connection (`connection connect a to b;`, no `: SomeDef`) is
|
|
1393
|
-
// the native binary connection with nothing further classifying it — the
|
|
1394
|
-
// keyword IS the type, `connect`, the same as `flow`/`bind` (R10-S6,
|
|
1395
|
-
// `ConnectsPhysically`'s migration). Before this it built to nothing at
|
|
1396
|
-
// all: the same silent-drop shape as `BindingUsage`/`ExposeMember`.
|
|
1397
|
-
// A typed connection normalizes its definition name: "Mitigates" → "mitigates".
|
|
1398
|
-
const normalizedType = typeName ? normalizeRelType(typeName) : 'connect';
|
|
1399
|
-
// Resolve source and target using registry for cross-file resolution
|
|
1400
|
-
const sourceId = resolveEndpointId(conn.source.ref, packageName, registry, allElementIds);
|
|
1401
|
-
const targetId = resolveEndpointId(conn.target.ref, packageName, registry, allElementIds);
|
|
1402
|
-
if (!sourceId || !targetId)
|
|
1403
|
-
return;
|
|
1404
|
-
// A named connection usage carries its own stable ID; anonymous ones fall
|
|
1405
|
-
// back to a positional counter that shifts whenever the file changes.
|
|
1406
|
-
// `extractAttributes` lifts metadata applications itself now, so the
|
|
1407
|
-
// connection path no longer needs its own second pass.
|
|
1408
|
-
const attributes = extractAttributes(conn.body);
|
|
1409
|
-
const rel = {
|
|
1410
|
-
id: conn.name || `rel-${++relationshipCounter}`,
|
|
1411
|
-
type: normalizedType,
|
|
1412
|
-
sourceId,
|
|
1413
|
-
// `connect a to b` omits the end names; the ends are then the inherited
|
|
1414
|
-
// `source`/`target` participants. csv-io already defaults the same way.
|
|
1415
|
-
sourceEnd: conn.source.endName ?? 'source',
|
|
1416
|
-
targetId,
|
|
1417
|
-
targetEnd: conn.target.endName ?? 'target',
|
|
1418
|
-
file: filePath,
|
|
1419
|
-
sourceRange: conn.$cstNode
|
|
1420
|
-
? { offset: conn.$cstNode.offset, length: conn.$cstNode.length }
|
|
1421
|
-
: undefined,
|
|
1422
|
-
named: conn.name ? true : undefined,
|
|
1423
|
-
attributes,
|
|
1424
|
-
flowItem: attributes.transportedItem || attributes.flowItem || undefined,
|
|
1425
|
-
};
|
|
1426
|
-
// Tag port IDs when endpoints reference port elements
|
|
1427
|
-
const sourceEl = elements.get(sourceId);
|
|
1428
|
-
if (sourceEl?.construct === 'port') {
|
|
1429
|
-
rel.sourcePortId = sourceId;
|
|
1430
|
-
}
|
|
1431
|
-
const targetEl = elements.get(targetId);
|
|
1432
|
-
if (targetEl?.construct === 'port') {
|
|
1433
|
-
rel.targetPortId = targetId;
|
|
1434
|
-
}
|
|
1435
|
-
relationships.push(rel);
|
|
1436
|
-
}
|
|
1437
|
-
/**
|
|
1438
|
-
* Resolve a dotted endpoint path to the deepest element it names.
|
|
1439
|
-
*
|
|
1440
|
-
* A dotted endpoint has two shapes and they resolve differently.
|
|
1441
|
-
*
|
|
1442
|
-
* `receive.prescription` names an action and one of its PARAMETERS. The
|
|
1443
|
-
* parameter is not an element, so the endpoint is the action and the parameter
|
|
1444
|
-
* is the end label.
|
|
1445
|
-
*
|
|
1446
|
-
* `touchscreen.touchUsbIo` names a port and a port NESTED inside it, and
|
|
1447
|
-
* `coffeeMachine.serviceInterface.diagnostics` nests one level deeper again.
|
|
1448
|
-
* The nested port IS an element in its own right, so the endpoint is the child.
|
|
1449
|
-
* Reading it the first way silently retargets the edge at the parent, which is
|
|
1450
|
-
* not a resolution failure anyone sees: it produces a plausible relationship
|
|
1451
|
-
* pointing at the wrong feature, and it only surfaces later as a payload
|
|
1452
|
-
* mismatch on whichever edge happened to carry a different item from its
|
|
1453
|
-
* parent's.
|
|
1454
|
-
*
|
|
1455
|
-
* Walk the path through the parent link and take the deepest real element.
|
|
1456
|
-
*
|
|
1457
|
-
* A nested part or port records its parent in `owner`; a nested ACTION records
|
|
1458
|
-
* it in `parentAction`, because the two are set by separate extraction paths.
|
|
1459
|
-
* Reading only `owner` broke the walk at the first hop of every function path:
|
|
1460
|
-
* `flow from fnDeliverTherapy.fnMeterFluid.fnMeasureDelivered to …` became a
|
|
1461
|
-
* self-loop on `fnDeliverTherapy`, which is a plausible-looking edge pointing
|
|
1462
|
-
* at the wrong function — the exact failure the comment above describes, one
|
|
1463
|
-
* field away from where it was fixed for ports.
|
|
1464
|
-
*/
|
|
1465
|
-
function resolveEndpoint(ref, elements) {
|
|
1466
|
-
const parts = ref.split('.');
|
|
1467
|
-
let id = parts[0];
|
|
1468
|
-
let i = 1;
|
|
1469
|
-
while (i < parts.length) {
|
|
1470
|
-
const child = elements.get(parts[i]);
|
|
1471
|
-
if (!child || (child.owner !== id && child.parentAction !== id))
|
|
1472
|
-
break;
|
|
1473
|
-
id = parts[i];
|
|
1474
|
-
i++;
|
|
1475
|
-
}
|
|
1476
|
-
return { id, end: parts.slice(i).join('.') };
|
|
1477
|
-
}
|
|
1478
|
-
/**
|
|
1479
|
-
* Resolve a `bind outer = inner;` port delegation into a MemoRelationship.
|
|
1480
|
-
*
|
|
1481
|
-
* Unlike a flow this carries no item: delegation is identity, so there is
|
|
1482
|
-
* nothing travelling and nothing to label the edge with. Consumers that render
|
|
1483
|
-
* an itemless edge already suppress the label.
|
|
1484
|
-
*/
|
|
1485
|
-
function resolveBinding(binding, filePath, _packageName, relationships, allElementIds, elements) {
|
|
1486
|
-
const sourceRef = binding.source;
|
|
1487
|
-
const targetRef = binding.target;
|
|
1488
|
-
if (!sourceRef || !targetRef)
|
|
1489
|
-
return;
|
|
1490
|
-
const { id: sourceId, end: sourceEnd } = resolveEndpoint(sourceRef, elements);
|
|
1491
|
-
const { id: targetId, end: targetEnd } = resolveEndpoint(targetRef, elements);
|
|
1492
|
-
if (!allElementIds.has(sourceId) || !allElementIds.has(targetId))
|
|
1493
|
-
return;
|
|
1494
|
-
relationships.push({
|
|
1495
|
-
id: `rel-${++relationshipCounter}`,
|
|
1496
|
-
type: 'bind',
|
|
1497
|
-
sourceId,
|
|
1498
|
-
sourceEnd,
|
|
1499
|
-
targetId,
|
|
1500
|
-
targetEnd,
|
|
1501
|
-
file: filePath,
|
|
1502
|
-
});
|
|
1503
|
-
}
|
|
1504
|
-
/**
|
|
1505
|
-
* Resolve a flow connection usage into a MemoRelationship.
|
|
1506
|
-
* Flow endpoints use dot notation: "actionName.paramName"
|
|
1507
|
-
*/
|
|
1508
|
-
function resolveFlowConnection(flow, filePath, packageName, parentActionId, relationships, allElementIds, elements) {
|
|
1509
|
-
const sourceRef = flow.source?.ref;
|
|
1510
|
-
const targetRef = flow.target?.ref;
|
|
1511
|
-
if (!sourceRef || !targetRef)
|
|
1512
|
-
return;
|
|
1513
|
-
const { id: sourceActionId, end: sourcePort } = resolveEndpoint(sourceRef, elements);
|
|
1514
|
-
const { id: targetActionId, end: targetPort } = resolveEndpoint(targetRef, elements);
|
|
1515
|
-
// Only create relationship if both endpoints reference known elements
|
|
1516
|
-
if (!allElementIds.has(sourceActionId) || !allElementIds.has(targetActionId))
|
|
1517
|
-
return;
|
|
1518
|
-
// A NAMED flow carries a stable ID that survives rebuilds; an anonymous one
|
|
1519
|
-
// falls back to a positional counter that shifts whenever the file changes.
|
|
1520
|
-
// Same rule `resolveConnection` applies to connection usages, and the same
|
|
1521
|
-
// reason: authoring needs to inspect, delete, and deep-link a flow, and a
|
|
1522
|
-
// positional id makes every one of those wrong after the next edit.
|
|
1523
|
-
const rel = {
|
|
1524
|
-
id: flow.name || `rel-${++relationshipCounter}`,
|
|
1525
|
-
type: 'flow',
|
|
1526
|
-
sourceId: sourceActionId,
|
|
1527
|
-
sourceEnd: sourcePort,
|
|
1528
|
-
targetId: targetActionId,
|
|
1529
|
-
targetEnd: targetPort,
|
|
1530
|
-
file: filePath,
|
|
1531
|
-
sourceRange: flow.$cstNode
|
|
1532
|
-
? { offset: flow.$cstNode.offset, length: flow.$cstNode.length }
|
|
1533
|
-
: undefined,
|
|
1534
|
-
named: flow.name ? true : undefined,
|
|
1535
|
-
attributes: extractAttributes(flow.body),
|
|
1536
|
-
flowItem: flow.itemType || undefined,
|
|
1537
|
-
};
|
|
1538
|
-
relationships.push(rel);
|
|
1539
|
-
}
|
|
1540
|
-
/**
|
|
1541
|
-
* Resolve a succession usage into pairs of MemoRelationships.
|
|
1542
|
-
* "first A then B" → (A→B).
|
|
1543
|
-
*
|
|
1544
|
-
* The grammar admits exactly one `then` per statement, matching KerML
|
|
1545
|
-
* `SuccessionDeclaration` (:845), so `steps` is always a pair here. The loop
|
|
1546
|
-
* below is still written over the whole array: it costs nothing, and it keeps
|
|
1547
|
-
* this function correct for the chained input the deferred-succession path at
|
|
1548
|
-
* the call site synthesizes.
|
|
1549
|
-
*/
|
|
1550
|
-
function resolveSuccession(succession, filePath, packageName, parentActionId, relationships, allElementIds) {
|
|
1551
|
-
const steps = succession.steps || [];
|
|
1552
|
-
if (steps.length < 2)
|
|
1553
|
-
return;
|
|
1554
|
-
for (let i = 0; i < steps.length - 1; i++) {
|
|
1555
|
-
const fromRef = steps[i].ref;
|
|
1556
|
-
const toRef = steps[i + 1].ref;
|
|
1557
|
-
// "start" and "done" are pseudo-elements; use parent action as context
|
|
1558
|
-
const sourceId = fromRef === 'start'
|
|
1559
|
-
? (parentActionId ? `${parentActionId}__start` : '__start')
|
|
1560
|
-
: fromRef;
|
|
1561
|
-
const targetId = toRef === 'done'
|
|
1562
|
-
? (parentActionId ? `${parentActionId}__done` : '__done')
|
|
1563
|
-
: toRef;
|
|
1564
|
-
// Skip if neither endpoint is a known element (allow start/done pseudo-elements)
|
|
1565
|
-
const sourceKnown = fromRef === 'start' || allElementIds.has(sourceId);
|
|
1566
|
-
const targetKnown = toRef === 'done' || allElementIds.has(targetId);
|
|
1567
|
-
if (!sourceKnown || !targetKnown)
|
|
1568
|
-
continue;
|
|
1569
|
-
const guardLabel = renderGuardExpression(steps[i].guard);
|
|
1570
|
-
const rel = {
|
|
1571
|
-
id: `rel-${++relationshipCounter}`,
|
|
1572
|
-
type: 'succession',
|
|
1573
|
-
sourceId,
|
|
1574
|
-
sourceEnd: guardLabel === undefined ? '' : `[${guardLabel}]`,
|
|
1575
|
-
targetId,
|
|
1576
|
-
targetEnd: '',
|
|
1577
|
-
file: filePath,
|
|
1578
|
-
};
|
|
1579
|
-
relationships.push(rel);
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
/**
|
|
1583
|
-
* Preserve a SysML succession guard as readable diagram text.
|
|
1584
|
-
*
|
|
1585
|
-
* Guards use the same expression AST as constraints. Previously only literal
|
|
1586
|
-
* `true`/`false` nodes happened to carry one of the three fields inspected by
|
|
1587
|
-
* the builder, so a valid guard such as `validUser == true` silently vanished
|
|
1588
|
-
* during lowering even though SysIDE accepted it.
|
|
1589
|
-
*/
|
|
1590
|
-
function renderGuardExpression(expr) {
|
|
1591
|
-
if (!expr)
|
|
1592
|
-
return undefined;
|
|
1593
|
-
switch (expr.$type) {
|
|
1594
|
-
case 'LiteralExpr':
|
|
1595
|
-
return expr.boolValue ?? expr.intValue ?? expr.strValue;
|
|
1596
|
-
case 'FeatureChain':
|
|
1597
|
-
return Array.isArray(expr.segments) ? expr.segments.join('.') : undefined;
|
|
1598
|
-
case 'UnaryExpr': {
|
|
1599
|
-
const operand = renderGuardExpression(expr.operand);
|
|
1600
|
-
return operand === undefined ? undefined : `${expr.op} ${operand}`;
|
|
1601
|
-
}
|
|
1602
|
-
case 'BinaryExpr': {
|
|
1603
|
-
const left = renderGuardExpression(expr.left);
|
|
1604
|
-
const right = renderGuardExpression(expr.right);
|
|
1605
|
-
return left === undefined || right === undefined
|
|
1606
|
-
? undefined
|
|
1607
|
-
: `${left} ${expr.op} ${right}`;
|
|
1608
|
-
}
|
|
1609
|
-
case 'CollectionOp': {
|
|
1610
|
-
const target = renderGuardExpression(expr.target);
|
|
1611
|
-
const argument = renderGuardExpression(expr.argument);
|
|
1612
|
-
if (target === undefined)
|
|
1613
|
-
return undefined;
|
|
1614
|
-
return `${target}->${expr.op}(${argument ?? ''})`;
|
|
1615
|
-
}
|
|
1616
|
-
default:
|
|
1617
|
-
return expr.text ?? expr.value;
|
|
1618
|
-
}
|
|
1619
|
-
}
|
|
1620
|
-
/**
|
|
1621
|
-
* Resolve an allocate usage into a MemoRelationship and set allocatedTo on the element.
|
|
1622
|
-
*/
|
|
1623
|
-
function resolveAllocate(allocate, filePath, packageName, elements, relationships, registry, allElementIds, relationshipRegistry) {
|
|
1624
|
-
const sourceRef = allocate.source;
|
|
1625
|
-
const targetRef = allocate.target;
|
|
1626
|
-
if (!sourceRef || !targetRef)
|
|
1627
|
-
return;
|
|
1628
|
-
// Resolve references
|
|
1629
|
-
const sourceId = resolveEndpointId(sourceRef, packageName, registry, allElementIds);
|
|
1630
|
-
const targetId = resolveEndpointId(targetRef, packageName, registry, allElementIds);
|
|
1631
|
-
if (!sourceId || !targetId)
|
|
1632
|
-
return;
|
|
1633
|
-
// Set allocatedTo on the source element
|
|
1634
|
-
const sourceEl = elements.get(sourceId);
|
|
1635
|
-
if (sourceEl) {
|
|
1636
|
-
sourceEl.allocatedTo = targetId;
|
|
1637
|
-
}
|
|
1638
|
-
// `allocate a to b;` and `connection : AllocatedTo connect …` are the same
|
|
1639
|
-
// statement, so they produce the same edge. They did not: the native form
|
|
1640
|
-
// emitted `allocateTo` with invented ends while the connection emitted
|
|
1641
|
-
// `allocatedTo` with the ontology's, and consumers keyed on one silently
|
|
1642
|
-
// missed the other — the DHF allocation queries ask for `allocatedTo`.
|
|
1643
|
-
//
|
|
1644
|
-
// A TYPED allocation — `allocation d : DeploysTo allocate m to node;` —
|
|
1645
|
-
// carries which allocation it is, and that distinction has to survive.
|
|
1646
|
-
// `DeploysTo` and `BuildsInto` are not `AllocatedTo` under another name:
|
|
1647
|
-
// they are separate edges the deployment views and the DHF read by name.
|
|
1648
|
-
// The `allocation def` naming them is what the typed form points at, so the
|
|
1649
|
-
// edge is its camelCase name whenever the registry knows it; an unknown or
|
|
1650
|
-
// absent type falls back to the base allocation, which is what bare
|
|
1651
|
-
// `allocate` has always meant.
|
|
1652
|
-
const typed = allocate.type ? pascalToCamelCase(allocate.type.split('::').pop()) : undefined;
|
|
1653
|
-
const edge = typed && relationshipRegistry?.has(typed) ? typed : 'allocatedTo';
|
|
1654
|
-
relationships.push(edge === 'allocatedTo'
|
|
1655
|
-
? nativeTraceEdge('allocatedTo', sourceId, targetId, filePath)
|
|
1656
|
-
: typedAllocationEdge(edge, sourceId, targetId, filePath, relationshipRegistry));
|
|
1657
|
-
}
|
|
1658
|
-
/**
|
|
1659
|
-
* The trace edge for an `allocation x : SomeAllocationDef allocate a to b;`.
|
|
1660
|
-
*
|
|
1661
|
-
* Ends come from the registry entry for the named definition, so a typed
|
|
1662
|
-
* allocation and the equivalent `connection : SomeAllocationDef connect …`
|
|
1663
|
-
* produce byte-identical links — the same guarantee the three
|
|
1664
|
-
* LANGUAGE_NATIVE_RELATIONS rows carry, extended to every allocation def the
|
|
1665
|
-
* ontology declares rather than to a fixed list of three.
|
|
1666
|
-
*/
|
|
1667
|
-
function typedAllocationEdge(type, sourceId, targetId, filePath, relationshipRegistry) {
|
|
1668
|
-
const ends = relationshipRegistry?.getRelType(type)?.ends ?? [];
|
|
1669
|
-
return {
|
|
1670
|
-
id: `rel-${++relationshipCounter}`,
|
|
1671
|
-
type,
|
|
1672
|
-
sourceId,
|
|
1673
|
-
sourceEnd: ends[0]?.name ?? 'source',
|
|
1674
|
-
targetId,
|
|
1675
|
-
targetEnd: ends[1]?.name ?? 'target',
|
|
1676
|
-
file: filePath,
|
|
1677
|
-
};
|
|
1678
|
-
}
|
|
1679
|
-
/** Build the trace edge for a language-native relation, typed from the registry. */
|
|
1680
|
-
function nativeTraceEdge(name, sourceId, targetId, filePath) {
|
|
1681
|
-
const [sourceEnd, targetEnd] = LANGUAGE_NATIVE_RELATIONS[name].ends;
|
|
1682
|
-
return {
|
|
1683
|
-
id: `rel-${++relationshipCounter}`,
|
|
1684
|
-
type: name,
|
|
1685
|
-
sourceId,
|
|
1686
|
-
sourceEnd: sourceEnd.name,
|
|
1687
|
-
targetId,
|
|
1688
|
-
targetEnd: targetEnd.name,
|
|
1689
|
-
file: filePath,
|
|
1690
|
-
};
|
|
1691
|
-
}
|
|
1692
|
-
/**
|
|
1693
|
-
* The owner context of a native trace usage: the package it is declared in, and
|
|
1694
|
-
* the nearest enclosing named element.
|
|
1695
|
-
*
|
|
1696
|
-
* `verify` needs the second one — the case that does the verifying is the owner
|
|
1697
|
-
* of the member, never a written end — and `satisfy` needs the first to resolve
|
|
1698
|
-
* its references the way every other endpoint is resolved.
|
|
1699
|
-
*/
|
|
1700
|
-
function nativeUsageContext(node) {
|
|
1701
|
-
const packages = [];
|
|
1702
|
-
let ownerId;
|
|
1703
|
-
for (let current = node.$container; current; current = current.$container) {
|
|
1704
|
-
if (current.$type === 'PackageDeclaration') {
|
|
1705
|
-
if (current.name)
|
|
1706
|
-
packages.unshift(current.name);
|
|
1707
|
-
continue;
|
|
1708
|
-
}
|
|
1709
|
-
// An `objective` is a MEMBERSHIP, not the element that does the
|
|
1710
|
-
// verifying — the standard writes `objective { verify r; }` inside the
|
|
1711
|
-
// case, and the case is the verifier. A named objective would otherwise
|
|
1712
|
-
// capture `ownerId` and the `verifiedBy` edge would point at a wrapper
|
|
1713
|
-
// that is not an extracted element, silently dropping the link.
|
|
1714
|
-
if (current.$type === 'ObjectiveMember')
|
|
1715
|
-
continue;
|
|
1716
|
-
if (ownerId === undefined && typeof current.name === 'string' && current.name) {
|
|
1717
|
-
ownerId = current.name;
|
|
1718
|
-
}
|
|
1719
|
-
}
|
|
1720
|
-
return { packageName: packages.join('::'), ownerId };
|
|
1721
|
-
}
|
|
1722
|
-
/**
|
|
1723
|
-
* Project a native usage that names ONE end and takes the other from its owner.
|
|
1724
|
-
*
|
|
1725
|
-
* `perform`, `include`, `exhibit` and `frame` all have this shape, and it is
|
|
1726
|
-
* `verify`'s shape with the ends swapped: `verify` names its source and owns
|
|
1727
|
-
* its target, these four own their source and name their target. Sharing the
|
|
1728
|
-
* resolution keeps the four from drifting apart, and keeps the rule that the
|
|
1729
|
-
* owner supplies the unwritten end stated in exactly one place.
|
|
1730
|
-
*/
|
|
1731
|
-
function resolveOwnerRootedUsage(node, written, name, filePath, relationships, registry, allElementIds) {
|
|
1732
|
-
if (!written)
|
|
1733
|
-
return;
|
|
1734
|
-
const { packageName, ownerId } = nativeUsageContext(node);
|
|
1735
|
-
const sourceId = ownerId
|
|
1736
|
-
? resolveEndpointId(ownerId, packageName, registry, allElementIds)
|
|
1737
|
-
: undefined;
|
|
1738
|
-
const targetId = resolveEndpointId(written, packageName, registry, allElementIds);
|
|
1739
|
-
if (!sourceId || !targetId)
|
|
1740
|
-
return;
|
|
1741
|
-
relationships.push(nativeTraceEdge(name, sourceId, targetId, filePath));
|
|
1742
|
-
}
|
|
1743
|
-
/**
|
|
1744
|
-
* Project a verification case's `subject` onto the `verifiedBy` edge.
|
|
1745
|
-
*
|
|
1746
|
-
* This is the standard's answer to verifying something that is not a
|
|
1747
|
-
* requirement: the verified element becomes the case's SUBJECT and the
|
|
1748
|
-
* requirement its `objective { verify … }`. 61 of MEMO's 99 `VerifiedBy` links
|
|
1749
|
-
* target a SystemFunction, a RiskControlMeasure, a SoftwareModule, a
|
|
1750
|
-
* BehaviorProperty or a TimingConstraint — none of which native `verify`
|
|
1751
|
-
* admits, because `verify` takes a RequirementUsage.
|
|
1752
|
-
*
|
|
1753
|
-
* The edge direction matches `VerifiedBy`: the subject is the source
|
|
1754
|
-
* (verificationTarget) and the owning case the target (verificationCase).
|
|
1755
|
-
*
|
|
1756
|
-
* A `subject` that declares a fresh feature rather than pointing at an existing
|
|
1757
|
-
* element — `subject testVehicle : Vehicle;` — binds nothing and contributes no
|
|
1758
|
-
* edge. Only the referring forms (`subject v :> vehicleTestConfig;`,
|
|
1759
|
-
* `subject v = vehicleTestConfig;`) name something already in the model. A
|
|
1760
|
-
* multi-valued subject is one parameter whose binding is a parenthesized list;
|
|
1761
|
-
* each bound element is one `verifiedBy` fact for the owning case.
|
|
1762
|
-
*/
|
|
1763
|
-
function resolveSubject(subject, filePath, relationships, registry, allElementIds) {
|
|
1764
|
-
if (!subject.boundRefs?.length)
|
|
1765
|
-
return;
|
|
1766
|
-
const { packageName, ownerId } = nativeUsageContext(subject);
|
|
1767
|
-
const targetId = ownerId
|
|
1768
|
-
? resolveEndpointId(ownerId, packageName, registry, allElementIds)
|
|
1769
|
-
: undefined;
|
|
1770
|
-
if (!targetId)
|
|
1771
|
-
return;
|
|
1772
|
-
for (const boundRef of subject.boundRefs) {
|
|
1773
|
-
const sourceId = resolveEndpointId(boundRef, packageName, registry, allElementIds);
|
|
1774
|
-
if (sourceId)
|
|
1775
|
-
relationships.push(nativeTraceEdge('verifiedBy', sourceId, targetId, filePath));
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
/**
|
|
1779
|
-
* Project a native `actor` onto the `participatesIn` edge (R10-S6).
|
|
1780
|
-
*
|
|
1781
|
-
* Same shape as `resolveSubject`: only the REFERRING form —
|
|
1782
|
-
* `actor driver = existingPart;` — names something already in the model, so
|
|
1783
|
-
* only that form produces an edge. A fresh declaration (`actor x : Person;`,
|
|
1784
|
-
* no `boundRef`) introduces a locally-scoped actor the model does not yet
|
|
1785
|
-
* have an element for; collapsing `MemoRelationship`'s `Initiates` and
|
|
1786
|
-
* `ParticipatesIn` onto the single native `actor` keyword means the
|
|
1787
|
-
* initiating/participating distinction is no longer a typed relationship —
|
|
1788
|
-
* it lives in how the actor is named, the same way `Composes` gave up its
|
|
1789
|
-
* whole/part distinction to plain nesting.
|
|
1790
|
-
*
|
|
1791
|
-
* The owner is the TARGET and the written reference the SOURCE — `verify`'s
|
|
1792
|
-
* shape, not `perform`'s: the use case is what the actor participates IN.
|
|
1793
|
-
*/
|
|
1794
|
-
function resolveActorParticipation(actor, filePath, relationships, registry, allElementIds) {
|
|
1795
|
-
if (!actor.boundRef)
|
|
1796
|
-
return;
|
|
1797
|
-
const { packageName, ownerId } = nativeUsageContext(actor);
|
|
1798
|
-
const sourceId = resolveEndpointId(actor.boundRef, packageName, registry, allElementIds);
|
|
1799
|
-
const targetId = ownerId ? resolveEndpointId(ownerId, packageName, registry, allElementIds) : undefined;
|
|
1800
|
-
if (!sourceId || !targetId)
|
|
1801
|
-
return;
|
|
1802
|
-
relationships.push(nativeTraceEdge('participatesIn', sourceId, targetId, filePath));
|
|
1803
|
-
}
|
|
1804
|
-
/**
|
|
1805
|
-
* Project every `dependency a to b;` onto the generic `dependency` edge, and
|
|
1806
|
-
* additionally onto `realizes` when it carries `#refinement` (R10-S6).
|
|
1807
|
-
*
|
|
1808
|
-
* The only native relation here that is not a connection. A Dependency takes n
|
|
1809
|
-
* clients and n suppliers rather than a source and a target, so one written
|
|
1810
|
-
* dependency can produce several edges — `dependency Schemata from s to a, b;`
|
|
1811
|
-
* is two statements sharing a name, and it lowers to two links, which is what
|
|
1812
|
-
* `Realizes` would have needed two connection usages to say.
|
|
1813
|
-
*
|
|
1814
|
-
* A dependency WITHOUT `#refinement` is an unclassified dependency: it means
|
|
1815
|
-
* strictly less than `Realizes` does, so it contributes only the generic
|
|
1816
|
-
* `dependency` edge, never `realizes` — inferring realization from a bare
|
|
1817
|
-
* dependency would put a claim in the traceability matrix that the model
|
|
1818
|
-
* never made. `#refinement` adds `realizes` on top; it does not replace the
|
|
1819
|
-
* generic edge, because a refinement dependency IS a dependency.
|
|
1820
|
-
*
|
|
1821
|
-
* Before R10-S6 a bare (non-`#refinement`) dependency built to nothing at
|
|
1822
|
-
* all — the same silent-drop shape as `BindingUsage`/`ExposeMember` — which
|
|
1823
|
-
* is what `ModuleUses`/`MonitorsChannel`'s migration to plain `dependency`
|
|
1824
|
-
* would otherwise have hit. Both collapse onto this one generic edge; native
|
|
1825
|
-
* `dependency` does not distinguish "uses a module" from "monitors a
|
|
1826
|
-
* channel" any more than `actor` distinguished an initiating actor from a
|
|
1827
|
-
* participating one, so that distinction now lives in the dependency's own
|
|
1828
|
-
* name/doc, not in a relationship type.
|
|
1829
|
-
*/
|
|
1830
|
-
function resolveDependency(dependency, filePath, relationships, registry, allElementIds) {
|
|
1831
|
-
const prefixes = (dependency.prefixMetadata ?? [])
|
|
1832
|
-
.map(annotation => annotation.type?.split('::').pop());
|
|
1833
|
-
const isRefinement = prefixes.includes(REFINEMENT_METADATA);
|
|
1834
|
-
const { packageName } = nativeUsageContext(dependency);
|
|
1835
|
-
for (const client of dependency.clients ?? []) {
|
|
1836
|
-
const sourceId = resolveEndpointId(client, packageName, registry, allElementIds);
|
|
1837
|
-
if (!sourceId)
|
|
1838
|
-
continue;
|
|
1839
|
-
for (const supplier of dependency.suppliers ?? []) {
|
|
1840
|
-
const targetId = resolveEndpointId(supplier, packageName, registry, allElementIds);
|
|
1841
|
-
if (!targetId)
|
|
1842
|
-
continue;
|
|
1843
|
-
relationships.push(nativeTraceEdge('dependency', sourceId, targetId, filePath));
|
|
1844
|
-
if (isRefinement)
|
|
1845
|
-
relationships.push(nativeTraceEdge('realizes', sourceId, targetId, filePath));
|
|
1846
|
-
}
|
|
1847
|
-
}
|
|
1848
|
-
}
|
|
1849
|
-
/**
|
|
1850
|
-
* Project every `satisfy` and `verify` in a document onto the trace edge its
|
|
1851
|
-
* MEMO connection-def equivalent produces.
|
|
1852
|
-
*/
|
|
1853
|
-
function resolveNativeTraceUsages(model, filePath, relationships, registry, allElementIds) {
|
|
1854
|
-
for (const node of AstUtils.streamAllContents(model)) {
|
|
1855
|
-
if (isSatisfyRequirementUsage(node)) {
|
|
1856
|
-
resolveSatisfy(node, filePath, relationships, registry, allElementIds);
|
|
1857
|
-
}
|
|
1858
|
-
else if (isRequirementVerificationMember(node)) {
|
|
1859
|
-
resolveVerify(node, filePath, relationships, registry, allElementIds);
|
|
1860
|
-
}
|
|
1861
|
-
else if (isPerformActionUsage(node)) {
|
|
1862
|
-
resolveOwnerRootedUsage(node, node.performed, 'performs', filePath, relationships, registry, allElementIds);
|
|
1863
|
-
}
|
|
1864
|
-
else if (isIncludeUseCaseUsage(node)) {
|
|
1865
|
-
resolveOwnerRootedUsage(node, node.included, 'includesStep', filePath, relationships, registry, allElementIds);
|
|
1866
|
-
}
|
|
1867
|
-
else if (isExhibitStateUsage(node)) {
|
|
1868
|
-
resolveOwnerRootedUsage(node, node.exhibited, 'exhibitsMode', filePath, relationships, registry, allElementIds);
|
|
1869
|
-
}
|
|
1870
|
-
else if (isFramedConcernMember(node)) {
|
|
1871
|
-
resolveOwnerRootedUsage(node, node.framed, 'framesConcern', filePath, relationships, registry, allElementIds);
|
|
1872
|
-
}
|
|
1873
|
-
else if (isSubjectMember(node)) {
|
|
1874
|
-
resolveSubject(node, filePath, relationships, registry, allElementIds);
|
|
1875
|
-
}
|
|
1876
|
-
else if (isActorMember(node)) {
|
|
1877
|
-
resolveActorParticipation(node, filePath, relationships, registry, allElementIds);
|
|
1878
|
-
}
|
|
1879
|
-
else if (isDependency(node)) {
|
|
1880
|
-
resolveDependency(node, filePath, relationships, registry, allElementIds);
|
|
1881
|
-
}
|
|
1882
|
-
else if (isVariantMember(node)) {
|
|
1883
|
-
resolveVariant(node, filePath, relationships, registry, allElementIds);
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
/**
|
|
1888
|
-
* Project `variant x;` onto a navigable choice-point edge.
|
|
1889
|
-
*
|
|
1890
|
-
* A variation's alternatives are memberships rather than connection usages,
|
|
1891
|
-
* so they would otherwise disappear from the consumer model entirely. The
|
|
1892
|
-
* nearest owner is the variation point and the written member names the
|
|
1893
|
-
* selected configuration. Keeping this as a first-class edge lets DSMs and
|
|
1894
|
-
* views distinguish a real choice from four unrelated parts.
|
|
1895
|
-
*/
|
|
1896
|
-
function resolveVariant(variant, filePath, relationships, registry, allElementIds) {
|
|
1897
|
-
const { packageName, ownerId } = nativeUsageContext(variant);
|
|
1898
|
-
const sourceId = ownerId
|
|
1899
|
-
? resolveEndpointId(ownerId, packageName, registry, allElementIds)
|
|
1900
|
-
: undefined;
|
|
1901
|
-
const targetId = resolveEndpointId(variant.name, packageName, registry, allElementIds);
|
|
1902
|
-
if (!sourceId || !targetId)
|
|
1903
|
-
return;
|
|
1904
|
-
relationships.push({
|
|
1905
|
-
id: `rel-${++relationshipCounter}`,
|
|
1906
|
-
type: 'variant',
|
|
1907
|
-
sourceId,
|
|
1908
|
-
sourceEnd: 'variationPoint',
|
|
1909
|
-
targetId,
|
|
1910
|
-
targetEnd: 'variant',
|
|
1911
|
-
file: filePath,
|
|
1912
|
-
});
|
|
1913
|
-
}
|
|
1914
|
-
function resolveSatisfy(satisfy, filePath, relationships, registry, allElementIds) {
|
|
1915
|
-
// A negated claim — `assert not satisfy r by p;` — states that the
|
|
1916
|
-
// requirement is NOT satisfied. There is no MEMO connection for it, and
|
|
1917
|
-
// emitting a `satisfiedBy` edge would make a design review's rejection read
|
|
1918
|
-
// as coverage in the traceability matrix. It parses; it contributes no
|
|
1919
|
-
// trace edge until the model has somewhere honest to put it.
|
|
1920
|
-
if (satisfy.isNegated)
|
|
1921
|
-
return;
|
|
1922
|
-
const { packageName } = nativeUsageContext(satisfy);
|
|
1923
|
-
const sourceId = resolveEndpointId(satisfy.requirement, packageName, registry, allElementIds);
|
|
1924
|
-
// Without `by`, the satisfying subject is inherited from the enclosing
|
|
1925
|
-
// requirement rather than written. Nothing to bind, so no edge.
|
|
1926
|
-
const targetId = satisfy.satisfyingFeature
|
|
1927
|
-
? resolveEndpointId(satisfy.satisfyingFeature, packageName, registry, allElementIds)
|
|
1928
|
-
: undefined;
|
|
1929
|
-
if (!sourceId || !targetId)
|
|
1930
|
-
return;
|
|
1931
|
-
relationships.push(nativeTraceEdge('satisfiedBy', sourceId, targetId, filePath));
|
|
1932
|
-
}
|
|
1933
|
-
function resolveVerify(verify, filePath, relationships, registry, allElementIds) {
|
|
1934
|
-
const { packageName, ownerId } = nativeUsageContext(verify);
|
|
1935
|
-
const sourceId = resolveEndpointId(verify.requirement, packageName, registry, allElementIds);
|
|
1936
|
-
// The verifying case is the owner. A `verify` whose owner is not an
|
|
1937
|
-
// extracted element — a bare `verification def`, say — has no second end
|
|
1938
|
-
// to bind, so it stays a parse fact and not a graph fact.
|
|
1939
|
-
const targetId = ownerId ? resolveEndpointId(ownerId, packageName, registry, allElementIds) : undefined;
|
|
1940
|
-
if (!sourceId || !targetId)
|
|
1941
|
-
return;
|
|
1942
|
-
relationships.push(nativeTraceEdge('verifiedBy', sourceId, targetId, filePath));
|
|
1943
|
-
}
|
|
1944
|
-
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
1945
|
-
function extractAttributes(body) {
|
|
1946
|
-
if (!body)
|
|
1947
|
-
return {};
|
|
1948
|
-
const attrs = {};
|
|
1949
|
-
for (const member of body) {
|
|
1950
|
-
if (member.$type === 'AttributeMember' || member.$type === 'RefMember' || member.$type === 'MetadataFeatureMember') {
|
|
1951
|
-
const attr = member;
|
|
1952
|
-
if (attr.value) {
|
|
1953
|
-
attrs[attr.name] = extractAttributeValue(attr.value);
|
|
1954
|
-
}
|
|
1955
|
-
else if (attr.type) {
|
|
1956
|
-
attrs[attr.name] = `<${attr.type}>`;
|
|
1957
|
-
}
|
|
1958
|
-
else if (attr.body?.length) {
|
|
1959
|
-
// Structured value: the members of an `attribute def` assigned
|
|
1960
|
-
// inline, e.g. `attribute :>> bounds { attribute :>> x = 0.1; }`.
|
|
1961
|
-
// Flattened to dotted keys ("bounds.x") so the value lands in
|
|
1962
|
-
// the same flat map every consumer already reads. Without this
|
|
1963
|
-
// branch the whole assignment is dropped and the model carries
|
|
1964
|
-
// no record of it.
|
|
1965
|
-
for (const [key, value] of Object.entries(extractAttributes(attr.body))) {
|
|
1966
|
-
attrs[`${attr.name}.${key}`] = value;
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
}
|
|
1971
|
-
// Metadata applications last, so an annotation overrides a directly declared
|
|
1972
|
-
// attribute of the same name. That order is what R10-S5 established for
|
|
1973
|
-
// connections and it is preserved here rather than re-litigated: while the
|
|
1974
|
-
// identification core is migrating off the base defs, an element may carry
|
|
1975
|
-
// both spellings, and the annotation is the newer statement of intent.
|
|
1976
|
-
Object.assign(attrs, extractMetadataApplications(body));
|
|
1977
|
-
return attrs;
|
|
1978
|
-
}
|
|
1979
|
-
/**
|
|
1980
|
-
* Standard metadata whose field name differs from the flat key MEMO reads.
|
|
1981
|
-
* Everything else lifts under its own field name, which is what makes one
|
|
1982
|
-
* `metadata def` usable as a carrier for any element.
|
|
1983
|
-
*/
|
|
1984
|
-
const METADATA_KEY_ALIASES = {
|
|
1985
|
-
Rationale: { text: 'rationale' },
|
|
1986
|
-
};
|
|
1987
|
-
/**
|
|
1988
|
-
* Lift every `@Foo { ... }` metadata application in a body into the flat
|
|
1989
|
-
* attribute map, under each field's own name.
|
|
1990
|
-
*
|
|
1991
|
-
* `extractAttributes`'s member walk covers `AttributeMember`/`RefMember`/
|
|
1992
|
-
* `MetadataFeatureMember`; a `MetadataApplication` is a different node type and
|
|
1993
|
-
* is invisible to it, so without this an annotation parses cleanly in both
|
|
1994
|
-
* parsers and then silently vanishes from the model — the BindingUsage /
|
|
1995
|
-
* ExposeMember / untyped-flow shape this codebase has already hit three times.
|
|
1996
|
-
*
|
|
1997
|
-
* This started (R10-S5, 2026-08-13) as a connection-only reader hardcoded to
|
|
1998
|
-
* `Rationale.text` and `StatusInfo.status`, because those were the two base-type
|
|
1999
|
-
* attributes being deleted at the time. It is general now for one reason: a
|
|
2000
|
-
* `metadata def` is the only carrier in SysML v2 that attaches to ANY metaclass,
|
|
2001
|
-
* so it is how MEMO can hold common fields (`id`, `uuid`, `sourceReference`, …)
|
|
2002
|
-
* without re-declaring them per metaclass. A carrier the builder cannot read is
|
|
2003
|
-
* not a carrier, so the reader has to be as general as the mechanism.
|
|
2004
|
-
*
|
|
2005
|
-
* Fields lift under their own names; `METADATA_KEY_ALIASES` covers the standard
|
|
2006
|
-
* definitions whose field name differs from the key MEMO reads.
|
|
2007
|
-
*/
|
|
2008
|
-
function extractMetadataApplications(body) {
|
|
2009
|
-
if (!body)
|
|
2010
|
-
return {};
|
|
2011
|
-
const attrs = {};
|
|
2012
|
-
for (const member of body) {
|
|
2013
|
-
if (member.$type !== 'MetadataApplication')
|
|
2014
|
-
continue;
|
|
2015
|
-
const metadataType = member.type?.split('::').pop() ?? '';
|
|
2016
|
-
const aliases = METADATA_KEY_ALIASES[metadataType] ?? {};
|
|
2017
|
-
for (const [field, value] of Object.entries(extractAttributes(member.body))) {
|
|
2018
|
-
if (value === '')
|
|
2019
|
-
continue;
|
|
2020
|
-
attrs[aliases[field] ?? field] = value;
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
return attrs;
|
|
2024
|
-
}
|
|
2025
|
-
function extractAttributeValue(value) {
|
|
2026
|
-
if (!value)
|
|
2027
|
-
return '';
|
|
2028
|
-
switch (value.$type) {
|
|
2029
|
-
case 'StringValue':
|
|
2030
|
-
return value.value.replace(/^"|"$/g, '');
|
|
2031
|
-
case 'IntValue':
|
|
2032
|
-
return String(value.value);
|
|
2033
|
-
case 'RealValue':
|
|
2034
|
-
return String(value.value);
|
|
2035
|
-
case 'BooleanValue':
|
|
2036
|
-
return value.value;
|
|
2037
|
-
case 'EnumValue':
|
|
2038
|
-
return value.enumRef;
|
|
2039
|
-
case 'SetLiteral':
|
|
2040
|
-
// { A, B, "c" } → "A, B, c" — keeps attributes flat and readable
|
|
2041
|
-
return (value.elements ?? [])
|
|
2042
|
-
.map(el => el.value ?? (el.stringValue ?? '').replace(/^"|"$/g, ''))
|
|
2043
|
-
.filter((s) => s.length > 0)
|
|
2044
|
-
.join(', ');
|
|
2045
|
-
default:
|
|
2046
|
-
return String(value);
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
function extractDocComment(body) {
|
|
2050
|
-
if (!body)
|
|
2051
|
-
return undefined;
|
|
2052
|
-
const doc = body.find((m) => m.$type === 'DocComment');
|
|
2053
|
-
if (!doc)
|
|
2054
|
-
return undefined;
|
|
2055
|
-
return doc.content
|
|
2056
|
-
.replace(/^doc\s+\/\*\s*/, '')
|
|
2057
|
-
.replace(/\s*\*\/$/, '')
|
|
2058
|
-
.replace(/\n\s*\*\s?/g, ' ')
|
|
2059
|
-
.trim();
|
|
2060
|
-
}
|
|
2061
|
-
/**
|
|
2062
|
-
* Resolve a QualifiedName reference to just the local name.
|
|
2063
|
-
* In SysML v2 usages: `control ::> rcFlowRateLimiter` — ref is "rcFlowRateLimiter"
|
|
2064
|
-
*/
|
|
2065
|
-
function resolveRef(ref) {
|
|
2066
|
-
if (!ref)
|
|
2067
|
-
return undefined;
|
|
2068
|
-
// Take the last segment of a qualified name
|
|
2069
|
-
const parts = ref.split('::');
|
|
2070
|
-
return parts[parts.length - 1] || undefined;
|
|
2071
|
-
}
|
|
2072
|
-
/**
|
|
2073
|
-
* Resolve a relationship endpoint reference to an element id, including
|
|
2074
|
-
* dotted feature chains (`sampleActionFlow.process.processStepB`): elements
|
|
2075
|
-
* are registered under their leaf name, so when the full reference is not a
|
|
2076
|
-
* known element id, resolve its last dot segment instead.
|
|
2077
|
-
*/
|
|
2078
|
-
function resolveEndpointId(
|
|
2079
|
-
// An endpoint can parse without a reference — the Release examples contain
|
|
2080
|
-
// connection forms the MEMO grammar accepts structurally but cannot bind.
|
|
2081
|
-
// An unresolvable endpoint drops the relationship at the call site, which
|
|
2082
|
-
// is the same outcome as any other unresolved reference; crashing the whole
|
|
2083
|
-
// build over it is not (§1.1 — the compiler reports, it does not refuse).
|
|
2084
|
-
ref, packageName, registry, allElementIds) {
|
|
2085
|
-
if (!ref)
|
|
2086
|
-
return undefined;
|
|
2087
|
-
const direct = registry.resolveElementId(ref, packageName, allElementIds) || resolveRef(ref);
|
|
2088
|
-
if (direct && allElementIds.has(direct))
|
|
2089
|
-
return direct;
|
|
2090
|
-
if (ref.includes('.')) {
|
|
2091
|
-
const leaf = ref.split('.').pop();
|
|
2092
|
-
const resolved = registry.resolveElementId(leaf, packageName, allElementIds) || resolveRef(leaf);
|
|
2093
|
-
if (resolved && allElementIds.has(resolved))
|
|
2094
|
-
return resolved;
|
|
2095
|
-
}
|
|
2096
|
-
return direct;
|
|
2097
|
-
}
|
|
2098
|
-
/**
|
|
2099
|
-
* Relationship type names are normalized by the shared helper in `naming.ts`,
|
|
2100
|
-
* which is the single definition of the source-name → model-key rule.
|
|
2101
|
-
*/
|
|
2102
|
-
const normalizeRelType = toModelType;
|
|
2103
|
-
//# sourceMappingURL=builder.js.map
|