@memoarchitect/tools 0.4.4
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/LICENSE +21 -0
- package/README.md +171 -0
- package/package.json +86 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.js +42 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.js.map +1 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.js +82 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.js.map +1 -0
- package/packages/tools/lib/__tests__/behavior.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/behavior.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/behavior.test.js +766 -0
- package/packages/tools/lib/__tests__/behavior.test.js.map +1 -0
- package/packages/tools/lib/__tests__/builder.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/builder.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/builder.test.js +728 -0
- package/packages/tools/lib/__tests__/builder.test.js.map +1 -0
- package/packages/tools/lib/__tests__/config-loader.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/config-loader.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/config-loader.test.js +196 -0
- package/packages/tools/lib/__tests__/config-loader.test.js.map +1 -0
- package/packages/tools/lib/__tests__/conformance.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/conformance.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/conformance.test.js +467 -0
- package/packages/tools/lib/__tests__/conformance.test.js.map +1 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.js +195 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.js.map +1 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.js +163 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.js.map +1 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.js +150 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.js.map +1 -0
- package/packages/tools/lib/__tests__/csv-io.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/csv-io.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/csv-io.test.js +317 -0
- package/packages/tools/lib/__tests__/csv-io.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.js +94 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.js +39 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dhf.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dhf.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dhf.test.js +393 -0
- package/packages/tools/lib/__tests__/dhf.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.js +85 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dsm.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dsm.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dsm.test.js +112 -0
- package/packages/tools/lib/__tests__/dsm.test.js.map +1 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.js +707 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.js.map +1 -0
- package/packages/tools/lib/__tests__/file-watcher.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/file-watcher.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/file-watcher.test.js +31 -0
- package/packages/tools/lib/__tests__/file-watcher.test.js.map +1 -0
- package/packages/tools/lib/__tests__/impact.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/impact.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/impact.test.js +82 -0
- package/packages/tools/lib/__tests__/impact.test.js.map +1 -0
- package/packages/tools/lib/__tests__/importer.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/importer.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/importer.test.js +336 -0
- package/packages/tools/lib/__tests__/importer.test.js.map +1 -0
- package/packages/tools/lib/__tests__/kind-registry.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/kind-registry.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/kind-registry.test.js +132 -0
- package/packages/tools/lib/__tests__/kind-registry.test.js.map +1 -0
- package/packages/tools/lib/__tests__/llm.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/llm.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/llm.test.js +275 -0
- package/packages/tools/lib/__tests__/llm.test.js.map +1 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.js +97 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.js.map +1 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.js +74 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.js.map +1 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.js +59 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.js.map +1 -0
- package/packages/tools/lib/__tests__/parser.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/parser.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/parser.test.js +938 -0
- package/packages/tools/lib/__tests__/parser.test.js.map +1 -0
- package/packages/tools/lib/__tests__/plugin.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/plugin.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/plugin.test.js +308 -0
- package/packages/tools/lib/__tests__/plugin.test.js.map +1 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.js +96 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.js.map +1 -0
- package/packages/tools/lib/__tests__/rule-registry.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/rule-registry.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/rule-registry.test.js +53 -0
- package/packages/tools/lib/__tests__/rule-registry.test.js.map +1 -0
- package/packages/tools/lib/__tests__/toolchain.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/toolchain.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/toolchain.test.js +94 -0
- package/packages/tools/lib/__tests__/toolchain.test.js.map +1 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.js +39 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.js.map +1 -0
- package/packages/tools/lib/__tests__/view-kinds.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/view-kinds.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/view-kinds.test.js +263 -0
- package/packages/tools/lib/__tests__/view-kinds.test.js.map +1 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.js +61 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.js.map +1 -0
- package/packages/tools/lib/analysis/dsm.d.ts +47 -0
- package/packages/tools/lib/analysis/dsm.d.ts.map +1 -0
- package/packages/tools/lib/analysis/dsm.js +172 -0
- package/packages/tools/lib/analysis/dsm.js.map +1 -0
- package/packages/tools/lib/analysis/impact.d.ts +35 -0
- package/packages/tools/lib/analysis/impact.d.ts.map +1 -0
- package/packages/tools/lib/analysis/impact.js +97 -0
- package/packages/tools/lib/analysis/impact.js.map +1 -0
- package/packages/tools/lib/bin/memo.d.ts +3 -0
- package/packages/tools/lib/bin/memo.d.ts.map +1 -0
- package/packages/tools/lib/bin/memo.js +461 -0
- package/packages/tools/lib/bin/memo.js.map +1 -0
- package/packages/tools/lib/browser/index.d.ts +13 -0
- package/packages/tools/lib/browser/index.d.ts.map +1 -0
- package/packages/tools/lib/browser/index.js +11 -0
- package/packages/tools/lib/browser/index.js.map +1 -0
- package/packages/tools/lib/commands/archetype-loader.d.ts +15 -0
- package/packages/tools/lib/commands/archetype-loader.d.ts.map +1 -0
- package/packages/tools/lib/commands/archetype-loader.js +31 -0
- package/packages/tools/lib/commands/archetype-loader.js.map +1 -0
- package/packages/tools/lib/commands/ask.d.ts +6 -0
- package/packages/tools/lib/commands/ask.d.ts.map +1 -0
- package/packages/tools/lib/commands/ask.js +79 -0
- package/packages/tools/lib/commands/ask.js.map +1 -0
- package/packages/tools/lib/commands/check.d.ts +6 -0
- package/packages/tools/lib/commands/check.d.ts.map +1 -0
- package/packages/tools/lib/commands/check.js +214 -0
- package/packages/tools/lib/commands/check.js.map +1 -0
- package/packages/tools/lib/commands/create-package.d.ts +12 -0
- package/packages/tools/lib/commands/create-package.d.ts.map +1 -0
- package/packages/tools/lib/commands/create-package.js +293 -0
- package/packages/tools/lib/commands/create-package.js.map +1 -0
- package/packages/tools/lib/commands/dev.d.ts +6 -0
- package/packages/tools/lib/commands/dev.d.ts.map +1 -0
- package/packages/tools/lib/commands/dev.js +316 -0
- package/packages/tools/lib/commands/dev.js.map +1 -0
- package/packages/tools/lib/commands/dhf-draft.d.ts +8 -0
- package/packages/tools/lib/commands/dhf-draft.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf-draft.js +115 -0
- package/packages/tools/lib/commands/dhf-draft.js.map +1 -0
- package/packages/tools/lib/commands/dhf-init.d.ts +4 -0
- package/packages/tools/lib/commands/dhf-init.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf-init.js +270 -0
- package/packages/tools/lib/commands/dhf-init.js.map +1 -0
- package/packages/tools/lib/commands/dhf-preview.d.ts +4 -0
- package/packages/tools/lib/commands/dhf-preview.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf-preview.js +285 -0
- package/packages/tools/lib/commands/dhf-preview.js.map +1 -0
- package/packages/tools/lib/commands/dhf.d.ts +27 -0
- package/packages/tools/lib/commands/dhf.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf.js +334 -0
- package/packages/tools/lib/commands/dhf.js.map +1 -0
- package/packages/tools/lib/commands/export.d.ts +9 -0
- package/packages/tools/lib/commands/export.d.ts.map +1 -0
- package/packages/tools/lib/commands/export.js +136 -0
- package/packages/tools/lib/commands/export.js.map +1 -0
- package/packages/tools/lib/commands/generate.d.ts +6 -0
- package/packages/tools/lib/commands/generate.d.ts.map +1 -0
- package/packages/tools/lib/commands/generate.js +80 -0
- package/packages/tools/lib/commands/generate.js.map +1 -0
- package/packages/tools/lib/commands/import-ea.d.ts +32 -0
- package/packages/tools/lib/commands/import-ea.d.ts.map +1 -0
- package/packages/tools/lib/commands/import-ea.js +156 -0
- package/packages/tools/lib/commands/import-ea.js.map +1 -0
- package/packages/tools/lib/commands/import-owl.d.ts +19 -0
- package/packages/tools/lib/commands/import-owl.d.ts.map +1 -0
- package/packages/tools/lib/commands/import-owl.js +103 -0
- package/packages/tools/lib/commands/import-owl.js.map +1 -0
- package/packages/tools/lib/commands/import-sysand.d.ts +11 -0
- package/packages/tools/lib/commands/import-sysand.d.ts.map +1 -0
- package/packages/tools/lib/commands/import-sysand.js +87 -0
- package/packages/tools/lib/commands/import-sysand.js.map +1 -0
- package/packages/tools/lib/commands/import.d.ts +30 -0
- package/packages/tools/lib/commands/import.d.ts.map +1 -0
- package/packages/tools/lib/commands/import.js +250 -0
- package/packages/tools/lib/commands/import.js.map +1 -0
- package/packages/tools/lib/commands/init-wizard.d.ts +10 -0
- package/packages/tools/lib/commands/init-wizard.d.ts.map +1 -0
- package/packages/tools/lib/commands/init-wizard.js +69 -0
- package/packages/tools/lib/commands/init-wizard.js.map +1 -0
- package/packages/tools/lib/commands/init.d.ts +30 -0
- package/packages/tools/lib/commands/init.d.ts.map +1 -0
- package/packages/tools/lib/commands/init.js +238 -0
- package/packages/tools/lib/commands/init.js.map +1 -0
- package/packages/tools/lib/commands/install.d.ts +8 -0
- package/packages/tools/lib/commands/install.d.ts.map +1 -0
- package/packages/tools/lib/commands/install.js +238 -0
- package/packages/tools/lib/commands/install.js.map +1 -0
- package/packages/tools/lib/commands/lock.d.ts +2 -0
- package/packages/tools/lib/commands/lock.d.ts.map +1 -0
- package/packages/tools/lib/commands/lock.js +29 -0
- package/packages/tools/lib/commands/lock.js.map +1 -0
- package/packages/tools/lib/commands/ontology.d.ts +14 -0
- package/packages/tools/lib/commands/ontology.d.ts.map +1 -0
- package/packages/tools/lib/commands/ontology.js +464 -0
- package/packages/tools/lib/commands/ontology.js.map +1 -0
- package/packages/tools/lib/commands/pack.d.ts +4 -0
- package/packages/tools/lib/commands/pack.d.ts.map +1 -0
- package/packages/tools/lib/commands/pack.js +89 -0
- package/packages/tools/lib/commands/pack.js.map +1 -0
- package/packages/tools/lib/commands/plugin.d.ts +10 -0
- package/packages/tools/lib/commands/plugin.d.ts.map +1 -0
- package/packages/tools/lib/commands/plugin.js +195 -0
- package/packages/tools/lib/commands/plugin.js.map +1 -0
- package/packages/tools/lib/commands/req.d.ts +10 -0
- package/packages/tools/lib/commands/req.d.ts.map +1 -0
- package/packages/tools/lib/commands/req.js +64 -0
- package/packages/tools/lib/commands/req.js.map +1 -0
- package/packages/tools/lib/commands/roundtrip.d.ts +6 -0
- package/packages/tools/lib/commands/roundtrip.d.ts.map +1 -0
- package/packages/tools/lib/commands/roundtrip.js +162 -0
- package/packages/tools/lib/commands/roundtrip.js.map +1 -0
- package/packages/tools/lib/commands/rules.d.ts +15 -0
- package/packages/tools/lib/commands/rules.d.ts.map +1 -0
- package/packages/tools/lib/commands/rules.js +282 -0
- package/packages/tools/lib/commands/rules.js.map +1 -0
- package/packages/tools/lib/commands/sysand-publish.d.ts +6 -0
- package/packages/tools/lib/commands/sysand-publish.d.ts.map +1 -0
- package/packages/tools/lib/commands/sysand-publish.js +231 -0
- package/packages/tools/lib/commands/sysand-publish.js.map +1 -0
- package/packages/tools/lib/commands/validate.d.ts +6 -0
- package/packages/tools/lib/commands/validate.d.ts.map +1 -0
- package/packages/tools/lib/commands/validate.js +269 -0
- package/packages/tools/lib/commands/validate.js.map +1 -0
- package/packages/tools/lib/completeness/tracker.d.ts +11 -0
- package/packages/tools/lib/completeness/tracker.d.ts.map +1 -0
- package/packages/tools/lib/completeness/tracker.js +86 -0
- package/packages/tools/lib/completeness/tracker.js.map +1 -0
- package/packages/tools/lib/dhf/dhf-config-v2.d.ts +102 -0
- package/packages/tools/lib/dhf/dhf-config-v2.d.ts.map +1 -0
- package/packages/tools/lib/dhf/dhf-config-v2.js +82 -0
- package/packages/tools/lib/dhf/dhf-config-v2.js.map +1 -0
- package/packages/tools/lib/dhf/dhf-config.d.ts +53 -0
- package/packages/tools/lib/dhf/dhf-config.d.ts.map +1 -0
- package/packages/tools/lib/dhf/dhf-config.js +44 -0
- package/packages/tools/lib/dhf/dhf-config.js.map +1 -0
- package/packages/tools/lib/dhf/directive-parser.d.ts +31 -0
- package/packages/tools/lib/dhf/directive-parser.d.ts.map +1 -0
- package/packages/tools/lib/dhf/directive-parser.js +83 -0
- package/packages/tools/lib/dhf/directive-parser.js.map +1 -0
- package/packages/tools/lib/dhf/document-compiler.d.ts +68 -0
- package/packages/tools/lib/dhf/document-compiler.d.ts.map +1 -0
- package/packages/tools/lib/dhf/document-compiler.js +209 -0
- package/packages/tools/lib/dhf/document-compiler.js.map +1 -0
- package/packages/tools/lib/dhf/document-ir.d.ts +170 -0
- package/packages/tools/lib/dhf/document-ir.d.ts.map +1 -0
- package/packages/tools/lib/dhf/document-ir.js +47 -0
- package/packages/tools/lib/dhf/document-ir.js.map +1 -0
- package/packages/tools/lib/dhf/document-registry.d.ts +45 -0
- package/packages/tools/lib/dhf/document-registry.d.ts.map +1 -0
- package/packages/tools/lib/dhf/document-registry.js +342 -0
- package/packages/tools/lib/dhf/document-registry.js.map +1 -0
- package/packages/tools/lib/dhf/export-plugin.d.ts +24 -0
- package/packages/tools/lib/dhf/export-plugin.d.ts.map +1 -0
- package/packages/tools/lib/dhf/export-plugin.js +24 -0
- package/packages/tools/lib/dhf/export-plugin.js.map +1 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.d.ts +15 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.d.ts.map +1 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.js +159 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.js.map +1 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.d.ts +9 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.d.ts.map +1 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.js +248 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.js.map +1 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.d.ts +9 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.d.ts.map +1 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.js +147 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.js.map +1 -0
- package/packages/tools/lib/dhf/index.d.ts +15 -0
- package/packages/tools/lib/dhf/index.d.ts.map +1 -0
- package/packages/tools/lib/dhf/index.js +21 -0
- package/packages/tools/lib/dhf/index.js.map +1 -0
- package/packages/tools/lib/dhf/markdown-to-ir.d.ts +19 -0
- package/packages/tools/lib/dhf/markdown-to-ir.d.ts.map +1 -0
- package/packages/tools/lib/dhf/markdown-to-ir.js +193 -0
- package/packages/tools/lib/dhf/markdown-to-ir.js.map +1 -0
- package/packages/tools/lib/dhf/query-engine.d.ts +61 -0
- package/packages/tools/lib/dhf/query-engine.d.ts.map +1 -0
- package/packages/tools/lib/dhf/query-engine.js +109 -0
- package/packages/tools/lib/dhf/query-engine.js.map +1 -0
- package/packages/tools/lib/dhf/query-executor.d.ts +33 -0
- package/packages/tools/lib/dhf/query-executor.d.ts.map +1 -0
- package/packages/tools/lib/dhf/query-executor.js +222 -0
- package/packages/tools/lib/dhf/query-executor.js.map +1 -0
- package/packages/tools/lib/dhf/script-runner.d.ts +4 -0
- package/packages/tools/lib/dhf/script-runner.d.ts.map +1 -0
- package/packages/tools/lib/dhf/script-runner.js +62 -0
- package/packages/tools/lib/dhf/script-runner.js.map +1 -0
- package/packages/tools/lib/dhf/snapshot.d.ts +60 -0
- package/packages/tools/lib/dhf/snapshot.d.ts.map +1 -0
- package/packages/tools/lib/dhf/snapshot.js +185 -0
- package/packages/tools/lib/dhf/snapshot.js.map +1 -0
- package/packages/tools/lib/dhf/template-engine.d.ts +18 -0
- package/packages/tools/lib/dhf/template-engine.d.ts.map +1 -0
- package/packages/tools/lib/dhf/template-engine.js +339 -0
- package/packages/tools/lib/dhf/template-engine.js.map +1 -0
- package/packages/tools/lib/dhf/template-resolver.d.ts +42 -0
- package/packages/tools/lib/dhf/template-resolver.d.ts.map +1 -0
- package/packages/tools/lib/dhf/template-resolver.js +196 -0
- package/packages/tools/lib/dhf/template-resolver.js.map +1 -0
- package/packages/tools/lib/import/column-mapper.d.ts +35 -0
- package/packages/tools/lib/import/column-mapper.d.ts.map +1 -0
- package/packages/tools/lib/import/column-mapper.js +171 -0
- package/packages/tools/lib/import/column-mapper.js.map +1 -0
- package/packages/tools/lib/import/import-diff.d.ts +49 -0
- package/packages/tools/lib/import/import-diff.d.ts.map +1 -0
- package/packages/tools/lib/import/import-diff.js +102 -0
- package/packages/tools/lib/import/import-diff.js.map +1 -0
- package/packages/tools/lib/import/recipes.d.ts +43 -0
- package/packages/tools/lib/import/recipes.d.ts.map +1 -0
- package/packages/tools/lib/import/recipes.js +133 -0
- package/packages/tools/lib/import/recipes.js.map +1 -0
- package/packages/tools/lib/importer/cameo-importer.d.ts +103 -0
- package/packages/tools/lib/importer/cameo-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/cameo-importer.js +384 -0
- package/packages/tools/lib/importer/cameo-importer.js.map +1 -0
- package/packages/tools/lib/importer/ea-importer.d.ts +115 -0
- package/packages/tools/lib/importer/ea-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/ea-importer.js +325 -0
- package/packages/tools/lib/importer/ea-importer.js.map +1 -0
- package/packages/tools/lib/importer/index.d.ts +5 -0
- package/packages/tools/lib/importer/index.d.ts.map +1 -0
- package/packages/tools/lib/importer/index.js +15 -0
- package/packages/tools/lib/importer/index.js.map +1 -0
- package/packages/tools/lib/importer/owl-importer.d.ts +91 -0
- package/packages/tools/lib/importer/owl-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/owl-importer.js +429 -0
- package/packages/tools/lib/importer/owl-importer.js.map +1 -0
- package/packages/tools/lib/importer/sysand-importer.d.ts +78 -0
- package/packages/tools/lib/importer/sysand-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/sysand-importer.js +188 -0
- package/packages/tools/lib/importer/sysand-importer.js.map +1 -0
- package/packages/tools/lib/index.d.ts +44 -0
- package/packages/tools/lib/index.d.ts.map +1 -0
- package/packages/tools/lib/index.js +56 -0
- package/packages/tools/lib/index.js.map +1 -0
- package/packages/tools/lib/language/generated/ast.d.ts +629 -0
- package/packages/tools/lib/language/generated/ast.d.ts.map +1 -0
- package/packages/tools/lib/language/generated/ast.js +961 -0
- package/packages/tools/lib/language/generated/ast.js.map +1 -0
- package/packages/tools/lib/language/generated/grammar.d.ts +7 -0
- package/packages/tools/lib/language/generated/grammar.d.ts.map +1 -0
- package/packages/tools/lib/language/generated/grammar.js +5676 -0
- package/packages/tools/lib/language/generated/grammar.js.map +1 -0
- package/packages/tools/lib/language/generated/module.d.ts +14 -0
- package/packages/tools/lib/language/generated/module.d.ts.map +1 -0
- package/packages/tools/lib/language/generated/module.js +21 -0
- package/packages/tools/lib/language/generated/module.js.map +1 -0
- package/packages/tools/lib/language/memo-sysml-module.d.ts +24 -0
- package/packages/tools/lib/language/memo-sysml-module.d.ts.map +1 -0
- package/packages/tools/lib/language/memo-sysml-module.js +20 -0
- package/packages/tools/lib/language/memo-sysml-module.js.map +1 -0
- package/packages/tools/lib/llm/ask-engine.d.ts +17 -0
- package/packages/tools/lib/llm/ask-engine.d.ts.map +1 -0
- package/packages/tools/lib/llm/ask-engine.js +43 -0
- package/packages/tools/lib/llm/ask-engine.js.map +1 -0
- package/packages/tools/lib/llm/draft-engine.d.ts +32 -0
- package/packages/tools/lib/llm/draft-engine.d.ts.map +1 -0
- package/packages/tools/lib/llm/draft-engine.js +270 -0
- package/packages/tools/lib/llm/draft-engine.js.map +1 -0
- package/packages/tools/lib/llm/generate-engine.d.ts +21 -0
- package/packages/tools/lib/llm/generate-engine.d.ts.map +1 -0
- package/packages/tools/lib/llm/generate-engine.js +83 -0
- package/packages/tools/lib/llm/generate-engine.js.map +1 -0
- package/packages/tools/lib/llm/index.d.ts +6 -0
- package/packages/tools/lib/llm/index.d.ts.map +1 -0
- package/packages/tools/lib/llm/index.js +11 -0
- package/packages/tools/lib/llm/index.js.map +1 -0
- package/packages/tools/lib/llm/llm-provider.d.ts +40 -0
- package/packages/tools/lib/llm/llm-provider.d.ts.map +1 -0
- package/packages/tools/lib/llm/llm-provider.js +121 -0
- package/packages/tools/lib/llm/llm-provider.js.map +1 -0
- package/packages/tools/lib/llm/model-context.d.ts +28 -0
- package/packages/tools/lib/llm/model-context.d.ts.map +1 -0
- package/packages/tools/lib/llm/model-context.js +162 -0
- package/packages/tools/lib/llm/model-context.js.map +1 -0
- package/packages/tools/lib/lock.d.ts +43 -0
- package/packages/tools/lib/lock.d.ts.map +1 -0
- package/packages/tools/lib/lock.js +225 -0
- package/packages/tools/lib/lock.js.map +1 -0
- package/packages/tools/lib/model/builder.d.ts +22 -0
- package/packages/tools/lib/model/builder.d.ts.map +1 -0
- package/packages/tools/lib/model/builder.js +708 -0
- package/packages/tools/lib/model/builder.js.map +1 -0
- package/packages/tools/lib/model/config-loader.d.ts +34 -0
- package/packages/tools/lib/model/config-loader.d.ts.map +1 -0
- package/packages/tools/lib/model/config-loader.js +257 -0
- package/packages/tools/lib/model/config-loader.js.map +1 -0
- package/packages/tools/lib/model/config.d.ts +220 -0
- package/packages/tools/lib/model/config.d.ts.map +1 -0
- package/packages/tools/lib/model/config.js +14 -0
- package/packages/tools/lib/model/config.js.map +1 -0
- package/packages/tools/lib/model/content-store.d.ts +8 -0
- package/packages/tools/lib/model/content-store.d.ts.map +1 -0
- package/packages/tools/lib/model/content-store.js +59 -0
- package/packages/tools/lib/model/content-store.js.map +1 -0
- package/packages/tools/lib/model/dimension-filter.d.ts +33 -0
- package/packages/tools/lib/model/dimension-filter.d.ts.map +1 -0
- package/packages/tools/lib/model/dimension-filter.js +57 -0
- package/packages/tools/lib/model/dimension-filter.js.map +1 -0
- package/packages/tools/lib/model/kind-registry.d.ts +72 -0
- package/packages/tools/lib/model/kind-registry.d.ts.map +1 -0
- package/packages/tools/lib/model/kind-registry.js +178 -0
- package/packages/tools/lib/model/kind-registry.js.map +1 -0
- package/packages/tools/lib/model/layer-resolver.d.ts +25 -0
- package/packages/tools/lib/model/layer-resolver.d.ts.map +1 -0
- package/packages/tools/lib/model/layer-resolver.js +82 -0
- package/packages/tools/lib/model/layer-resolver.js.map +1 -0
- package/packages/tools/lib/model/manifest.d.ts +23 -0
- package/packages/tools/lib/model/manifest.d.ts.map +1 -0
- package/packages/tools/lib/model/manifest.js +117 -0
- package/packages/tools/lib/model/manifest.js.map +1 -0
- package/packages/tools/lib/model/methodology-loader.d.ts +56 -0
- package/packages/tools/lib/model/methodology-loader.d.ts.map +1 -0
- package/packages/tools/lib/model/methodology-loader.js +203 -0
- package/packages/tools/lib/model/methodology-loader.js.map +1 -0
- package/packages/tools/lib/model/ontology-loader.d.ts +113 -0
- package/packages/tools/lib/model/ontology-loader.d.ts.map +1 -0
- package/packages/tools/lib/model/ontology-loader.js +901 -0
- package/packages/tools/lib/model/ontology-loader.js.map +1 -0
- package/packages/tools/lib/model/package-registry.d.ts +62 -0
- package/packages/tools/lib/model/package-registry.d.ts.map +1 -0
- package/packages/tools/lib/model/package-registry.js +164 -0
- package/packages/tools/lib/model/package-registry.js.map +1 -0
- package/packages/tools/lib/model/parser-utils.d.ts +23 -0
- package/packages/tools/lib/model/parser-utils.d.ts.map +1 -0
- package/packages/tools/lib/model/parser-utils.js +63 -0
- package/packages/tools/lib/model/parser-utils.js.map +1 -0
- package/packages/tools/lib/model/paths.d.ts +18 -0
- package/packages/tools/lib/model/paths.d.ts.map +1 -0
- package/packages/tools/lib/model/paths.js +26 -0
- package/packages/tools/lib/model/paths.js.map +1 -0
- package/packages/tools/lib/model/relationship-registry.d.ts +64 -0
- package/packages/tools/lib/model/relationship-registry.d.ts.map +1 -0
- package/packages/tools/lib/model/relationship-registry.js +141 -0
- package/packages/tools/lib/model/relationship-registry.js.map +1 -0
- package/packages/tools/lib/model/semantic.d.ts +175 -0
- package/packages/tools/lib/model/semantic.d.ts.map +1 -0
- package/packages/tools/lib/model/semantic.js +61 -0
- package/packages/tools/lib/model/semantic.js.map +1 -0
- package/packages/tools/lib/model/short-id.d.ts +32 -0
- package/packages/tools/lib/model/short-id.d.ts.map +1 -0
- package/packages/tools/lib/model/short-id.js +136 -0
- package/packages/tools/lib/model/short-id.js.map +1 -0
- package/packages/tools/lib/model/toolchain.d.ts +12 -0
- package/packages/tools/lib/model/toolchain.d.ts.map +1 -0
- package/packages/tools/lib/model/toolchain.js +92 -0
- package/packages/tools/lib/model/toolchain.js.map +1 -0
- package/packages/tools/lib/model/view-deriver.d.ts +22 -0
- package/packages/tools/lib/model/view-deriver.d.ts.map +1 -0
- package/packages/tools/lib/model/view-deriver.js +160 -0
- package/packages/tools/lib/model/view-deriver.js.map +1 -0
- package/packages/tools/lib/model/view-kinds.d.ts +29 -0
- package/packages/tools/lib/model/view-kinds.d.ts.map +1 -0
- package/packages/tools/lib/model/view-kinds.js +80 -0
- package/packages/tools/lib/model/view-kinds.js.map +1 -0
- package/packages/tools/lib/ontology/owl-exporter.d.ts +43 -0
- package/packages/tools/lib/ontology/owl-exporter.d.ts.map +1 -0
- package/packages/tools/lib/ontology/owl-exporter.js +70 -0
- package/packages/tools/lib/ontology/owl-exporter.js.map +1 -0
- package/packages/tools/lib/operations/index.d.ts +8 -0
- package/packages/tools/lib/operations/index.d.ts.map +1 -0
- package/packages/tools/lib/operations/index.js +8 -0
- package/packages/tools/lib/operations/index.js.map +1 -0
- package/packages/tools/lib/operations/project-snapshot.d.ts +17 -0
- package/packages/tools/lib/operations/project-snapshot.d.ts.map +1 -0
- package/packages/tools/lib/operations/project-snapshot.js +103 -0
- package/packages/tools/lib/operations/project-snapshot.js.map +1 -0
- package/packages/tools/lib/plugin/index.d.ts +5 -0
- package/packages/tools/lib/plugin/index.d.ts.map +1 -0
- package/packages/tools/lib/plugin/index.js +10 -0
- package/packages/tools/lib/plugin/index.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-loader.d.ts +26 -0
- package/packages/tools/lib/plugin/plugin-loader.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-loader.js +216 -0
- package/packages/tools/lib/plugin/plugin-loader.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-registry.d.ts +49 -0
- package/packages/tools/lib/plugin/plugin-registry.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-registry.js +121 -0
- package/packages/tools/lib/plugin/plugin-registry.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-scaffold.d.ts +17 -0
- package/packages/tools/lib/plugin/plugin-scaffold.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-scaffold.js +223 -0
- package/packages/tools/lib/plugin/plugin-scaffold.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-types.d.ts +115 -0
- package/packages/tools/lib/plugin/plugin-types.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-types.js +11 -0
- package/packages/tools/lib/plugin/plugin-types.js.map +1 -0
- package/packages/tools/lib/protocol/messages.d.ts +470 -0
- package/packages/tools/lib/protocol/messages.d.ts.map +1 -0
- package/packages/tools/lib/protocol/messages.js +6 -0
- package/packages/tools/lib/protocol/messages.js.map +1 -0
- package/packages/tools/lib/serializer/csv-io.d.ts +113 -0
- package/packages/tools/lib/serializer/csv-io.d.ts.map +1 -0
- package/packages/tools/lib/serializer/csv-io.js +394 -0
- package/packages/tools/lib/serializer/csv-io.js.map +1 -0
- package/packages/tools/lib/serializer/sysml-generator.d.ts +32 -0
- package/packages/tools/lib/serializer/sysml-generator.d.ts.map +1 -0
- package/packages/tools/lib/serializer/sysml-generator.js +120 -0
- package/packages/tools/lib/serializer/sysml-generator.js.map +1 -0
- package/packages/tools/lib/server/config-resolver.d.ts +14 -0
- package/packages/tools/lib/server/config-resolver.d.ts.map +1 -0
- package/packages/tools/lib/server/config-resolver.js +54 -0
- package/packages/tools/lib/server/config-resolver.js.map +1 -0
- package/packages/tools/lib/server/dev-server.d.ts +17 -0
- package/packages/tools/lib/server/dev-server.d.ts.map +1 -0
- package/packages/tools/lib/server/dev-server.js +939 -0
- package/packages/tools/lib/server/dev-server.js.map +1 -0
- package/packages/tools/lib/server/dhf-doc-store.d.ts +11 -0
- package/packages/tools/lib/server/dhf-doc-store.d.ts.map +1 -0
- package/packages/tools/lib/server/dhf-doc-store.js +181 -0
- package/packages/tools/lib/server/dhf-doc-store.js.map +1 -0
- package/packages/tools/lib/server/file-watcher.d.ts +20 -0
- package/packages/tools/lib/server/file-watcher.d.ts.map +1 -0
- package/packages/tools/lib/server/file-watcher.js +140 -0
- package/packages/tools/lib/server/file-watcher.js.map +1 -0
- package/packages/tools/lib/server/persistor.d.ts +25 -0
- package/packages/tools/lib/server/persistor.d.ts.map +1 -0
- package/packages/tools/lib/server/persistor.js +100 -0
- package/packages/tools/lib/server/persistor.js.map +1 -0
- package/packages/tools/lib/server/view-layout-store.d.ts +8 -0
- package/packages/tools/lib/server/view-layout-store.d.ts.map +1 -0
- package/packages/tools/lib/server/view-layout-store.js +73 -0
- package/packages/tools/lib/server/view-layout-store.js.map +1 -0
- package/packages/tools/lib/types/index.d.ts +4 -0
- package/packages/tools/lib/types/index.d.ts.map +1 -0
- package/packages/tools/lib/types/index.js +6 -0
- package/packages/tools/lib/types/index.js.map +1 -0
- package/packages/tools/lib/validator/behavior-validator.d.ts +12 -0
- package/packages/tools/lib/validator/behavior-validator.d.ts.map +1 -0
- package/packages/tools/lib/validator/behavior-validator.js +124 -0
- package/packages/tools/lib/validator/behavior-validator.js.map +1 -0
- package/packages/tools/lib/validator/constraint-eval.d.ts +90 -0
- package/packages/tools/lib/validator/constraint-eval.d.ts.map +1 -0
- package/packages/tools/lib/validator/constraint-eval.js +478 -0
- package/packages/tools/lib/validator/constraint-eval.js.map +1 -0
- package/packages/tools/lib/validator/constraint-loader.d.ts +10 -0
- package/packages/tools/lib/validator/constraint-loader.d.ts.map +1 -0
- package/packages/tools/lib/validator/constraint-loader.js +113 -0
- package/packages/tools/lib/validator/constraint-loader.js.map +1 -0
- package/packages/tools/lib/validator/rule-engine.d.ts +13 -0
- package/packages/tools/lib/validator/rule-engine.d.ts.map +1 -0
- package/packages/tools/lib/validator/rule-engine.js +38 -0
- package/packages/tools/lib/validator/rule-engine.js.map +1 -0
- package/packages/tools/lib/validator/rule-registry.d.ts +61 -0
- package/packages/tools/lib/validator/rule-registry.d.ts.map +1 -0
- package/packages/tools/lib/validator/rule-registry.js +142 -0
- package/packages/tools/lib/validator/rule-registry.js.map +1 -0
- package/packages/tools/lib/validator/types.d.ts +59 -0
- package/packages/tools/lib/validator/types.d.ts.map +1 -0
- package/packages/tools/lib/validator/types.js +3 -0
- package/packages/tools/lib/validator/types.js.map +1 -0
- package/packages/tools/lib/validator/view-validator.d.ts +11 -0
- package/packages/tools/lib/validator/view-validator.d.ts.map +1 -0
- package/packages/tools/lib/validator/view-validator.js +48 -0
- package/packages/tools/lib/validator/view-validator.js.map +1 -0
- package/packages/tools/src/grammar/memo-sysml.langium +450 -0
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { EmptyFileSystem } from 'langium';
|
|
5
|
+
import { parseHelper } from 'langium/test';
|
|
6
|
+
import { createMemoSysMLServices } from '../language/memo-sysml-module.js';
|
|
7
|
+
import { buildMemoModel } from '../model/builder.js';
|
|
8
|
+
import { KindRegistry } from '../model/kind-registry.js';
|
|
9
|
+
import { RelationshipRegistry } from '../model/relationship-registry.js';
|
|
10
|
+
import { validateModel } from '../validator/rule-engine.js';
|
|
11
|
+
import { computeCompleteness } from '../completeness/tracker.js';
|
|
12
|
+
import { loadConfig, resolveConfig } from '../model/config-loader.js';
|
|
13
|
+
const services = createMemoSysMLServices({ ...EmptyFileSystem }).MemoSysML;
|
|
14
|
+
const parse = parseHelper(services);
|
|
15
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
16
|
+
async function parseDoc(source, filePath = 'test.sysml') {
|
|
17
|
+
const doc = await parse(source);
|
|
18
|
+
return { document: doc, filePath };
|
|
19
|
+
}
|
|
20
|
+
/** Minimal config for testing */
|
|
21
|
+
const testConfig = {
|
|
22
|
+
projectName: 'test',
|
|
23
|
+
projectType: 'device',
|
|
24
|
+
kinds: {
|
|
25
|
+
Hazard: { label: 'Hazard', layer: 'risk', sysmlConstruct: 'requirement def' },
|
|
26
|
+
RiskControl: { label: 'Risk Control', layer: 'risk', sysmlConstruct: 'requirement def' },
|
|
27
|
+
SystemRequirement: { label: 'System Req', layer: 'requirements', sysmlConstruct: 'requirement def' },
|
|
28
|
+
SoftwareRequirement: { label: 'Software Req', layer: 'requirements', sysmlConstruct: 'requirement def' },
|
|
29
|
+
Software: { label: 'Software', layer: 'software', sysmlConstruct: 'part def' },
|
|
30
|
+
Actor: { label: 'Actor', layer: 'business', sysmlConstruct: 'part def' },
|
|
31
|
+
},
|
|
32
|
+
relationshipTypes: [
|
|
33
|
+
{ name: 'mitigates', label: 'Mitigates', layer: 'risk', color: '#E74C3C' },
|
|
34
|
+
{ name: 'traceTo', label: 'Trace To', layer: 'requirements', color: '#4A90D9' },
|
|
35
|
+
],
|
|
36
|
+
architectureLayers: [
|
|
37
|
+
{ id: 'risk', label: 'Risk', color: '#E74C3C' },
|
|
38
|
+
{ id: 'requirements', label: 'Requirements', color: '#4A90D9' },
|
|
39
|
+
{ id: 'software', label: 'Software', color: '#F39C12' },
|
|
40
|
+
{ id: 'business', label: 'Business', color: '#8E44AD' },
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
// ─── Tests ──────────────────────────────────────────────────────────────────
|
|
44
|
+
describe('buildMemoModel', () => {
|
|
45
|
+
it('extracts elements from part usages', async () => {
|
|
46
|
+
const doc = await parseDoc(`
|
|
47
|
+
package TestPkg {
|
|
48
|
+
part clinician : Actor {
|
|
49
|
+
attribute redefines name = "Clinician";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
`);
|
|
53
|
+
const model = buildMemoModel([doc], testConfig);
|
|
54
|
+
expect(model.elements.size).toBe(1);
|
|
55
|
+
const el = model.elements.get('clinician');
|
|
56
|
+
expect(el).toBeDefined();
|
|
57
|
+
expect(el.kind).toBe('Actor');
|
|
58
|
+
expect(el.construct).toBe('part');
|
|
59
|
+
expect(el.layer).toBe('business');
|
|
60
|
+
expect(el.name).toBe('Clinician');
|
|
61
|
+
expect(el.attributes['name']).toBe('Clinician');
|
|
62
|
+
});
|
|
63
|
+
it('extracts elements from requirement usages', async () => {
|
|
64
|
+
const doc = await parseDoc(`
|
|
65
|
+
package TestPkg {
|
|
66
|
+
requirement hazOverInfusion : Hazard {
|
|
67
|
+
attribute redefines hazardId = "HAZ-001";
|
|
68
|
+
attribute redefines title = "Over-Infusion";
|
|
69
|
+
doc /* A hazard description. */
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
`);
|
|
73
|
+
const model = buildMemoModel([doc], testConfig);
|
|
74
|
+
expect(model.elements.size).toBe(1);
|
|
75
|
+
const el = model.elements.get('hazOverInfusion');
|
|
76
|
+
expect(el.kind).toBe('Hazard');
|
|
77
|
+
expect(el.construct).toBe('requirement');
|
|
78
|
+
expect(el.layer).toBe('risk');
|
|
79
|
+
expect(el.name).toBe('Over-Infusion');
|
|
80
|
+
expect(el.attributes['hazardId']).toBe('HAZ-001');
|
|
81
|
+
expect(el.doc).toContain('hazard description');
|
|
82
|
+
});
|
|
83
|
+
it('extracts connection usages as relationships', async () => {
|
|
84
|
+
const doc = await parseDoc(`
|
|
85
|
+
package TestPkg {
|
|
86
|
+
requirement rc1 : RiskControl {
|
|
87
|
+
attribute redefines title = "Control 1";
|
|
88
|
+
}
|
|
89
|
+
requirement haz1 : Hazard {
|
|
90
|
+
attribute redefines title = "Hazard 1";
|
|
91
|
+
}
|
|
92
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> haz1;
|
|
93
|
+
}
|
|
94
|
+
`);
|
|
95
|
+
const model = buildMemoModel([doc], testConfig);
|
|
96
|
+
expect(model.elements.size).toBe(2);
|
|
97
|
+
expect(model.relationships).toHaveLength(1);
|
|
98
|
+
const rel = model.relationships[0];
|
|
99
|
+
expect(rel.type).toBe('mitigates');
|
|
100
|
+
expect(rel.sourceId).toBe('rc1');
|
|
101
|
+
expect(rel.sourceEnd).toBe('control');
|
|
102
|
+
expect(rel.targetId).toBe('haz1');
|
|
103
|
+
expect(rel.targetEnd).toBe('hazard');
|
|
104
|
+
});
|
|
105
|
+
it('builds element indexes by kind and layer', async () => {
|
|
106
|
+
const doc = await parseDoc(`
|
|
107
|
+
package TestPkg {
|
|
108
|
+
requirement h1 : Hazard { attribute redefines title = "H1"; }
|
|
109
|
+
requirement h2 : Hazard { attribute redefines title = "H2"; }
|
|
110
|
+
requirement sr1 : SystemRequirement { attribute redefines title = "SR1"; }
|
|
111
|
+
}
|
|
112
|
+
`);
|
|
113
|
+
const model = buildMemoModel([doc], testConfig);
|
|
114
|
+
expect(model.elementsByKind.get('Hazard')?.length).toBe(2);
|
|
115
|
+
expect(model.elementsByKind.get('SystemRequirement')?.length).toBe(1);
|
|
116
|
+
expect(model.elementsByLayer.get('risk')?.length).toBe(2);
|
|
117
|
+
expect(model.elementsByLayer.get('requirements')?.length).toBe(1);
|
|
118
|
+
});
|
|
119
|
+
it('builds relationship indexes (outgoing, incoming, byType)', async () => {
|
|
120
|
+
const doc = await parseDoc(`
|
|
121
|
+
package TestPkg {
|
|
122
|
+
requirement rc1 : RiskControl { attribute redefines title = "RC1"; }
|
|
123
|
+
requirement h1 : Hazard { attribute redefines title = "H1"; }
|
|
124
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> h1;
|
|
125
|
+
}
|
|
126
|
+
`);
|
|
127
|
+
const model = buildMemoModel([doc], testConfig);
|
|
128
|
+
expect(model.outgoing.get('rc1')?.length).toBe(1);
|
|
129
|
+
expect(model.incoming.get('h1')?.length).toBe(1);
|
|
130
|
+
expect(model.relationshipsByType.get('mitigates')?.length).toBe(1);
|
|
131
|
+
});
|
|
132
|
+
it('parses real (float) literal attribute values', async () => {
|
|
133
|
+
const doc = await parseDoc(`
|
|
134
|
+
package TestPkg {
|
|
135
|
+
part sw1 : Software {
|
|
136
|
+
attribute redefines name = "SW1";
|
|
137
|
+
attribute periodMs = 20.0;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
`);
|
|
141
|
+
const model = buildMemoModel([doc], testConfig);
|
|
142
|
+
expect(model.errors).toHaveLength(0);
|
|
143
|
+
expect(model.elements.get('sw1')?.attributes['periodMs']).toBe('20.0');
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe('computeCompleteness', () => {
|
|
147
|
+
it('computes per-layer completeness', async () => {
|
|
148
|
+
const doc = await parseDoc(`
|
|
149
|
+
package TestPkg {
|
|
150
|
+
requirement h1 : Hazard { attribute redefines title = "H1"; }
|
|
151
|
+
requirement rc1 : RiskControl { attribute redefines title = "RC1"; }
|
|
152
|
+
part sw1 : Software { attribute redefines safetyClassification = "C"; }
|
|
153
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> h1;
|
|
154
|
+
}
|
|
155
|
+
`);
|
|
156
|
+
const model = buildMemoModel([doc], testConfig);
|
|
157
|
+
const validation = validateModel(model);
|
|
158
|
+
const report = computeCompleteness(model, validation, testConfig);
|
|
159
|
+
expect(report.totalElements).toBe(3);
|
|
160
|
+
// h1 passes (has mitigates), rc1 has no rules, sw1 passes (has attribute)
|
|
161
|
+
expect(report.overall).toBeGreaterThanOrEqual(50);
|
|
162
|
+
expect(report.layers.length).toBe(4); // risk, requirements, software, business
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
// ─── Cross-file import resolution tests ─────────────────────────────────────
|
|
166
|
+
describe('Cross-file import resolution', () => {
|
|
167
|
+
it('tracks package names on elements', async () => {
|
|
168
|
+
const doc = await parseDoc(`
|
|
169
|
+
package DeviceModel {
|
|
170
|
+
part clinician : Actor {
|
|
171
|
+
attribute redefines name = "Clinician";
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
`);
|
|
175
|
+
const model = buildMemoModel([doc], testConfig);
|
|
176
|
+
const el = model.elements.get('clinician');
|
|
177
|
+
expect(el.package).toBe('DeviceModel');
|
|
178
|
+
});
|
|
179
|
+
it('resolves connections across two files via wildcard import', async () => {
|
|
180
|
+
const riskFile = await parseDoc(`
|
|
181
|
+
package RiskPkg {
|
|
182
|
+
requirement haz1 : Hazard {
|
|
183
|
+
attribute redefines title = "Over-Infusion";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
`, 'model/risk.sysml');
|
|
187
|
+
const controlFile = await parseDoc(`
|
|
188
|
+
package ControlPkg {
|
|
189
|
+
import RiskPkg::*;
|
|
190
|
+
requirement rc1 : RiskControl {
|
|
191
|
+
attribute redefines title = "Flow Limiter";
|
|
192
|
+
}
|
|
193
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> haz1;
|
|
194
|
+
}
|
|
195
|
+
`, 'model/controls.sysml');
|
|
196
|
+
const model = buildMemoModel([riskFile, controlFile], testConfig);
|
|
197
|
+
expect(model.elements.size).toBe(2);
|
|
198
|
+
expect(model.elements.get('haz1')?.package).toBe('RiskPkg');
|
|
199
|
+
expect(model.elements.get('rc1')?.package).toBe('ControlPkg');
|
|
200
|
+
expect(model.relationships).toHaveLength(1);
|
|
201
|
+
expect(model.relationships[0].sourceId).toBe('rc1');
|
|
202
|
+
expect(model.relationships[0].targetId).toBe('haz1');
|
|
203
|
+
});
|
|
204
|
+
it('resolves connections across files via named import', async () => {
|
|
205
|
+
const riskFile = await parseDoc(`
|
|
206
|
+
package RiskPkg {
|
|
207
|
+
requirement haz1 : Hazard {
|
|
208
|
+
attribute redefines title = "Over-Infusion";
|
|
209
|
+
}
|
|
210
|
+
requirement haz2 : Hazard {
|
|
211
|
+
attribute redefines title = "Under-Infusion";
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
`, 'model/risk.sysml');
|
|
215
|
+
const controlFile = await parseDoc(`
|
|
216
|
+
package ControlPkg {
|
|
217
|
+
import RiskPkg::haz1;
|
|
218
|
+
requirement rc1 : RiskControl {
|
|
219
|
+
attribute redefines title = "Flow Limiter";
|
|
220
|
+
}
|
|
221
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> haz1;
|
|
222
|
+
}
|
|
223
|
+
`, 'model/controls.sysml');
|
|
224
|
+
const model = buildMemoModel([riskFile, controlFile], testConfig);
|
|
225
|
+
expect(model.relationships).toHaveLength(1);
|
|
226
|
+
expect(model.relationships[0].targetId).toBe('haz1');
|
|
227
|
+
});
|
|
228
|
+
it('resolves qualified name references in connections', async () => {
|
|
229
|
+
const riskFile = await parseDoc(`
|
|
230
|
+
package RiskPkg {
|
|
231
|
+
requirement haz1 : Hazard {
|
|
232
|
+
attribute redefines title = "Over-Infusion";
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
`, 'model/risk.sysml');
|
|
236
|
+
const controlFile = await parseDoc(`
|
|
237
|
+
package ControlPkg {
|
|
238
|
+
requirement rc1 : RiskControl {
|
|
239
|
+
attribute redefines title = "Flow Limiter";
|
|
240
|
+
}
|
|
241
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> RiskPkg::haz1;
|
|
242
|
+
}
|
|
243
|
+
`, 'model/controls.sysml');
|
|
244
|
+
const model = buildMemoModel([riskFile, controlFile], testConfig);
|
|
245
|
+
expect(model.relationships).toHaveLength(1);
|
|
246
|
+
expect(model.relationships[0].targetId).toBe('haz1');
|
|
247
|
+
});
|
|
248
|
+
it('handles nested packages', async () => {
|
|
249
|
+
const doc = await parseDoc(`
|
|
250
|
+
package DeviceModel {
|
|
251
|
+
package Risk {
|
|
252
|
+
requirement haz1 : Hazard {
|
|
253
|
+
attribute redefines title = "H1";
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
package Controls {
|
|
257
|
+
import DeviceModel::Risk::*;
|
|
258
|
+
requirement rc1 : RiskControl {
|
|
259
|
+
attribute redefines title = "RC1";
|
|
260
|
+
}
|
|
261
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> haz1;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
`);
|
|
265
|
+
const model = buildMemoModel([doc], testConfig);
|
|
266
|
+
expect(model.elements.get('haz1')?.package).toBe('DeviceModel::Risk');
|
|
267
|
+
expect(model.elements.get('rc1')?.package).toBe('DeviceModel::Controls');
|
|
268
|
+
expect(model.relationships).toHaveLength(1);
|
|
269
|
+
});
|
|
270
|
+
it('resolves qualified type names for kinds', async () => {
|
|
271
|
+
const doc = await parseDoc(`
|
|
272
|
+
package TestPkg {
|
|
273
|
+
requirement h1 : RiskPkg::Hazard {
|
|
274
|
+
attribute redefines title = "H1";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
`);
|
|
278
|
+
const model = buildMemoModel([doc], testConfig);
|
|
279
|
+
const el = model.elements.get('h1');
|
|
280
|
+
// Should resolve RiskPkg::Hazard to just "Hazard" for kind lookup
|
|
281
|
+
expect(el.kind).toBe('Hazard');
|
|
282
|
+
expect(el.layer).toBe('risk');
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
// ─── Library package tests ──────────────────────────────────────────────────
|
|
286
|
+
describe('SysML v2 library keyword', () => {
|
|
287
|
+
it('parses library package declaration', async () => {
|
|
288
|
+
const doc = await parseDoc(`
|
|
289
|
+
library package MEMO_Types {
|
|
290
|
+
part def Hazard;
|
|
291
|
+
part def RiskControl;
|
|
292
|
+
}
|
|
293
|
+
`);
|
|
294
|
+
const model = buildMemoModel([doc], testConfig);
|
|
295
|
+
// Library packages contain definitions, not usages — no elements extracted
|
|
296
|
+
expect(model.elements.size).toBe(0);
|
|
297
|
+
});
|
|
298
|
+
it('library package is tracked in registry', async () => {
|
|
299
|
+
const { PackageRegistry } = await import('../model/package-registry.js');
|
|
300
|
+
const registry = new PackageRegistry();
|
|
301
|
+
const doc = await parseDoc(`
|
|
302
|
+
library package MEMO_Types {
|
|
303
|
+
part def Hazard;
|
|
304
|
+
}
|
|
305
|
+
package DeviceModel {
|
|
306
|
+
import MEMO_Types::*;
|
|
307
|
+
requirement h1 : Hazard {
|
|
308
|
+
attribute redefines title = "H1";
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
`);
|
|
312
|
+
registry.buildFromDocuments([doc]);
|
|
313
|
+
expect(registry.isLibraryPackage('MEMO_Types')).toBe(true);
|
|
314
|
+
expect(registry.isLibraryPackage('DeviceModel')).toBe(false);
|
|
315
|
+
});
|
|
316
|
+
it('library and non-library packages coexist', async () => {
|
|
317
|
+
const libFile = await parseDoc(`
|
|
318
|
+
library package OntologyLib {
|
|
319
|
+
part def Hazard;
|
|
320
|
+
part def Actor;
|
|
321
|
+
}
|
|
322
|
+
`, 'lib/ontology.sysml');
|
|
323
|
+
const modelFile = await parseDoc(`
|
|
324
|
+
package InfusionPump {
|
|
325
|
+
import OntologyLib::*;
|
|
326
|
+
part clinician : Actor {
|
|
327
|
+
attribute redefines name = "Clinician";
|
|
328
|
+
}
|
|
329
|
+
requirement h1 : Hazard {
|
|
330
|
+
attribute redefines title = "H1";
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
`, 'model/pump.sysml');
|
|
334
|
+
const model = buildMemoModel([libFile, modelFile], testConfig);
|
|
335
|
+
// Only model elements (not definitions from library)
|
|
336
|
+
expect(model.elements.size).toBe(2);
|
|
337
|
+
expect(model.elements.get('clinician')?.package).toBe('InfusionPump');
|
|
338
|
+
expect(model.elements.get('h1')?.package).toBe('InfusionPump');
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
// ─── Multi-file model splitting tests ───────────────────────────────────────
|
|
342
|
+
describe('Multi-file model splitting', () => {
|
|
343
|
+
it('builds model from split files with cross-package connections', async () => {
|
|
344
|
+
const riskFile = await parseDoc(`
|
|
345
|
+
package DeviceRisk {
|
|
346
|
+
requirement haz1 : Hazard {
|
|
347
|
+
attribute redefines title = "Over-Infusion";
|
|
348
|
+
}
|
|
349
|
+
requirement rc1 : RiskControl {
|
|
350
|
+
attribute redefines title = "Flow Limiter";
|
|
351
|
+
}
|
|
352
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> haz1;
|
|
353
|
+
}
|
|
354
|
+
`, 'model/risk/risk.sysml');
|
|
355
|
+
const reqFile = await parseDoc(`
|
|
356
|
+
package DeviceRequirements {
|
|
357
|
+
import DeviceRisk::*;
|
|
358
|
+
requirement sr1 : SystemRequirement {
|
|
359
|
+
attribute redefines title = "Flow Accuracy";
|
|
360
|
+
}
|
|
361
|
+
connection : TraceTo connect source ::> sr1 to target ::> rc1;
|
|
362
|
+
}
|
|
363
|
+
`, 'model/requirements/requirements.sysml');
|
|
364
|
+
const archFile = await parseDoc(`
|
|
365
|
+
package DeviceArchitecture {
|
|
366
|
+
import DeviceRequirements::*;
|
|
367
|
+
part pump : Actor {
|
|
368
|
+
attribute redefines name = "Pump Mechanism";
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
`, 'model/architecture/architecture.sysml');
|
|
372
|
+
const model = buildMemoModel([riskFile, reqFile, archFile], testConfig);
|
|
373
|
+
// All elements from all files
|
|
374
|
+
expect(model.elements.size).toBe(4);
|
|
375
|
+
expect(model.elements.get('haz1')?.package).toBe('DeviceRisk');
|
|
376
|
+
expect(model.elements.get('sr1')?.package).toBe('DeviceRequirements');
|
|
377
|
+
expect(model.elements.get('pump')?.package).toBe('DeviceArchitecture');
|
|
378
|
+
// Cross-file connections
|
|
379
|
+
expect(model.relationships.length).toBe(2);
|
|
380
|
+
// Mitigates: rc1 → haz1 (within risk file)
|
|
381
|
+
const mitigates = model.relationships.find(r => r.type === 'mitigates');
|
|
382
|
+
expect(mitigates?.sourceId).toBe('rc1');
|
|
383
|
+
expect(mitigates?.targetId).toBe('haz1');
|
|
384
|
+
// TraceTo: sr1 → rc1 (cross-file: requirements → risk)
|
|
385
|
+
const traceTo = model.relationships.find(r => r.type === 'traceTo');
|
|
386
|
+
expect(traceTo?.sourceId).toBe('sr1');
|
|
387
|
+
expect(traceTo?.targetId).toBe('rc1');
|
|
388
|
+
});
|
|
389
|
+
it('resolves three-level cross-file chains', async () => {
|
|
390
|
+
const riskFile = await parseDoc(`
|
|
391
|
+
package Risk {
|
|
392
|
+
requirement haz1 : Hazard {
|
|
393
|
+
attribute redefines title = "H1";
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
`, 'risk.sysml');
|
|
397
|
+
const reqFile = await parseDoc(`
|
|
398
|
+
package Requirements {
|
|
399
|
+
import Risk::*;
|
|
400
|
+
requirement sr1 : SystemRequirement {
|
|
401
|
+
attribute redefines title = "SR1";
|
|
402
|
+
}
|
|
403
|
+
connection : TraceTo connect source ::> sr1 to target ::> haz1;
|
|
404
|
+
}
|
|
405
|
+
`, 'requirements.sysml');
|
|
406
|
+
const swFile = await parseDoc(`
|
|
407
|
+
package Software {
|
|
408
|
+
import Requirements::*;
|
|
409
|
+
requirement swr1 : SoftwareRequirement {
|
|
410
|
+
attribute redefines title = "SWR1";
|
|
411
|
+
}
|
|
412
|
+
connection : TraceTo connect source ::> swr1 to target ::> sr1;
|
|
413
|
+
}
|
|
414
|
+
`, 'software.sysml');
|
|
415
|
+
const model = buildMemoModel([riskFile, reqFile, swFile], testConfig);
|
|
416
|
+
expect(model.elements.size).toBe(3);
|
|
417
|
+
expect(model.relationships.length).toBe(2);
|
|
418
|
+
// sr1 → haz1 (req → risk)
|
|
419
|
+
const r1 = model.relationships.find(r => r.sourceId === 'sr1');
|
|
420
|
+
expect(r1?.targetId).toBe('haz1');
|
|
421
|
+
// swr1 → sr1 (software → requirements)
|
|
422
|
+
const r2 = model.relationships.find(r => r.sourceId === 'swr1');
|
|
423
|
+
expect(r2?.targetId).toBe('sr1');
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
// ─── Dotted feature-chain endpoint resolution ─────────────────────────────
|
|
427
|
+
// Elements are registered under their leaf name, so relationship endpoints
|
|
428
|
+
// written as feature chains (`sampleActionFlow.receive`) must resolve to the
|
|
429
|
+
// leaf element id — this is how the gpca-pump AFD sample includes nested
|
|
430
|
+
// actions in its view and allocates them to lanes.
|
|
431
|
+
describe('Dotted feature-chain endpoints', () => {
|
|
432
|
+
const source = `
|
|
433
|
+
package TestPkg {
|
|
434
|
+
part laneA : Software { attribute name = "Lane A"; }
|
|
435
|
+
action wrapper {
|
|
436
|
+
action receive;
|
|
437
|
+
action process {
|
|
438
|
+
action stepA;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
allocate wrapper.receive to laneA;
|
|
442
|
+
allocate wrapper.process.stepA to laneA;
|
|
443
|
+
connection : TraceTo connect source ::> wrapper.receive to target ::> laneA;
|
|
444
|
+
}
|
|
445
|
+
`;
|
|
446
|
+
it('resolves dotted allocate endpoints to leaf element ids', async () => {
|
|
447
|
+
const model = buildMemoModel([await parseDoc(source)], testConfig);
|
|
448
|
+
const allocations = model.relationships.filter(r => r.type === 'allocateTo');
|
|
449
|
+
expect(allocations.map(r => r.sourceId).sort()).toEqual(['receive', 'stepA']);
|
|
450
|
+
expect(model.elements.get('receive')?.allocatedTo).toBe('laneA');
|
|
451
|
+
expect(model.elements.get('stepA')?.allocatedTo).toBe('laneA');
|
|
452
|
+
});
|
|
453
|
+
it('resolves dotted connection endpoints to leaf element ids', async () => {
|
|
454
|
+
const model = buildMemoModel([await parseDoc(source)], testConfig);
|
|
455
|
+
const trace = model.relationships.find(r => r.type === 'traceTo');
|
|
456
|
+
expect(trace?.sourceId).toBe('receive');
|
|
457
|
+
expect(trace?.targetId).toBe('laneA');
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
// ─── M-2: Port wiring tests ───────────────────────────────────────────────
|
|
461
|
+
describe('Port wiring (M-2)', () => {
|
|
462
|
+
it('populates portSpec on port usage elements', async () => {
|
|
463
|
+
const doc = await parseDoc(`
|
|
464
|
+
package TestPkg {
|
|
465
|
+
in port ~sensorIn : SensorPort;
|
|
466
|
+
out port controlOut : ControlPort;
|
|
467
|
+
port plain : GenericPort;
|
|
468
|
+
}
|
|
469
|
+
`);
|
|
470
|
+
const model = buildMemoModel([doc], testConfig);
|
|
471
|
+
const sensor = model.elements.get('sensorIn');
|
|
472
|
+
expect(sensor).toBeDefined();
|
|
473
|
+
expect(sensor.construct).toBe('port');
|
|
474
|
+
expect(sensor.portSpec).toBeDefined();
|
|
475
|
+
expect(sensor.portSpec.type).toBe('SensorPort');
|
|
476
|
+
expect(sensor.portSpec.direction).toBe('in');
|
|
477
|
+
expect(sensor.portSpec.isConjugated).toBe(true);
|
|
478
|
+
const control = model.elements.get('controlOut');
|
|
479
|
+
expect(control.portSpec.direction).toBe('out');
|
|
480
|
+
expect(control.portSpec.isConjugated).toBe(false);
|
|
481
|
+
const plain = model.elements.get('plain');
|
|
482
|
+
expect(plain.portSpec.direction).toBeUndefined();
|
|
483
|
+
expect(plain.portSpec.isConjugated).toBe(false);
|
|
484
|
+
});
|
|
485
|
+
it('sets owner and ownedPorts for ports inside part def', async () => {
|
|
486
|
+
const doc = await parseDoc(`
|
|
487
|
+
package TestPkg {
|
|
488
|
+
part def PumpController {
|
|
489
|
+
in port sensorIn : SensorPort;
|
|
490
|
+
out port controlOut : ControlPort;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
`);
|
|
494
|
+
const model = buildMemoModel([doc], testConfig);
|
|
495
|
+
// Ports extracted as elements
|
|
496
|
+
expect(model.elements.size).toBe(2);
|
|
497
|
+
const sensor = model.elements.get('sensorIn');
|
|
498
|
+
expect(sensor).toBeDefined();
|
|
499
|
+
expect(sensor.owner).toBe('PumpController');
|
|
500
|
+
expect(sensor.portSpec.direction).toBe('in');
|
|
501
|
+
const control = model.elements.get('controlOut');
|
|
502
|
+
expect(control.owner).toBe('PumpController');
|
|
503
|
+
expect(control.portSpec.direction).toBe('out');
|
|
504
|
+
});
|
|
505
|
+
it('tags port IDs on connection endpoints', async () => {
|
|
506
|
+
const doc = await parseDoc(`
|
|
507
|
+
package TestPkg {
|
|
508
|
+
port sensorOut : SensorPort;
|
|
509
|
+
port sensorIn : SensorPort;
|
|
510
|
+
connection : DataLink connect source ::> sensorOut to target ::> sensorIn;
|
|
511
|
+
}
|
|
512
|
+
`);
|
|
513
|
+
const config = {
|
|
514
|
+
...testConfig,
|
|
515
|
+
relationshipTypes: [
|
|
516
|
+
...(testConfig.relationshipTypes ?? []),
|
|
517
|
+
{ name: 'dataLink', label: 'Data Link', layer: 'interfaces', color: '#3498DB' },
|
|
518
|
+
],
|
|
519
|
+
};
|
|
520
|
+
const model = buildMemoModel([doc], config);
|
|
521
|
+
expect(model.relationships).toHaveLength(1);
|
|
522
|
+
const rel = model.relationships[0];
|
|
523
|
+
expect(rel.sourcePortId).toBe('sensorOut');
|
|
524
|
+
expect(rel.targetPortId).toBe('sensorIn');
|
|
525
|
+
});
|
|
526
|
+
it('does not set port IDs when endpoints are not ports', async () => {
|
|
527
|
+
const doc = await parseDoc(`
|
|
528
|
+
package TestPkg {
|
|
529
|
+
requirement rc1 : RiskControl { attribute redefines title = "RC1"; }
|
|
530
|
+
requirement h1 : Hazard { attribute redefines title = "H1"; }
|
|
531
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> h1;
|
|
532
|
+
}
|
|
533
|
+
`);
|
|
534
|
+
const model = buildMemoModel([doc], testConfig);
|
|
535
|
+
const rel = model.relationships[0];
|
|
536
|
+
expect(rel.sourcePortId).toBeUndefined();
|
|
537
|
+
expect(rel.targetPortId).toBeUndefined();
|
|
538
|
+
});
|
|
539
|
+
});
|
|
540
|
+
// ─── Helper: resolve extends chain for tests ────────────────────────────────
|
|
541
|
+
function loadResolvedConfig(configPath) {
|
|
542
|
+
const config = loadConfig(configPath);
|
|
543
|
+
return resolveConfig(config, (packageName) => {
|
|
544
|
+
// Map @memo package names to workspace package configs
|
|
545
|
+
const shortName = packageName.replace(/^@memo\//, '');
|
|
546
|
+
const parentPath = resolve('/Users/someshkashyap/sandbox/memo/packages', shortName, 'memo.package.yaml');
|
|
547
|
+
try {
|
|
548
|
+
return loadConfig(parentPath);
|
|
549
|
+
}
|
|
550
|
+
catch {
|
|
551
|
+
return undefined;
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
// ─── Integration test with real infusion-pump file ──────────────────────────
|
|
556
|
+
// SKIP: examples/infusion-pump/ removed in c22b2e3 (single-example branch decision).
|
|
557
|
+
// Restore fixture or repoint to gpca-pump when builder work resumes.
|
|
558
|
+
describe.skip('Infusion pump integration', () => {
|
|
559
|
+
const PUMP_FILE = resolve('/Users/someshkashyap/sandbox/memo/examples/infusion-pump/model/infusion-pump.sysml');
|
|
560
|
+
const CONFIG_FILE = resolve('/Users/someshkashyap/sandbox/memo/packages/medical-modeling-profile/memo.package.yaml');
|
|
561
|
+
it('builds model from infusion-pump.sysml', async () => {
|
|
562
|
+
const source = readFileSync(PUMP_FILE, 'utf-8');
|
|
563
|
+
const doc = await parse(source);
|
|
564
|
+
const config = loadResolvedConfig(CONFIG_FILE);
|
|
565
|
+
const model = buildMemoModel([{ document: doc, filePath: 'model/infusion-pump.sysml' }], config);
|
|
566
|
+
// Should have many elements (actors, requirements, hazards, components, etc.)
|
|
567
|
+
expect(model.elements.size).toBeGreaterThan(50);
|
|
568
|
+
// Should have relationships across risk, derivation, allocation, satisfaction, and verification.
|
|
569
|
+
expect(model.relationships.length).toBeGreaterThan(30);
|
|
570
|
+
// Check specific elements
|
|
571
|
+
expect(model.elements.get('clinician')).toBeDefined();
|
|
572
|
+
expect(model.elements.get('clinician')?.kind).toBe('Actor');
|
|
573
|
+
expect(model.elements.get('hazOverInfusion')).toBeDefined();
|
|
574
|
+
expect(model.elements.get('hazOverInfusion')?.kind).toBe('Hazard');
|
|
575
|
+
// Check relationships
|
|
576
|
+
const mitigates = model.relationshipsByType.get('mitigates') || [];
|
|
577
|
+
expect(mitigates.length).toBe(3); // 3 risk controls
|
|
578
|
+
const traceTo = model.relationshipsByType.get('traceTo') || [];
|
|
579
|
+
expect(traceTo.length).toBe(0);
|
|
580
|
+
const derives = model.relationshipsByType.get('derives') || [];
|
|
581
|
+
const refines = model.relationshipsByType.get('refines') || [];
|
|
582
|
+
expect(derives.length).toBeGreaterThanOrEqual(6);
|
|
583
|
+
expect(refines.length).toBeGreaterThanOrEqual(5);
|
|
584
|
+
// Verify relationship indexes
|
|
585
|
+
const hazOverOutgoing = model.outgoing.get('hazOverInfusion') || [];
|
|
586
|
+
const hazOverIncoming = model.incoming.get('hazOverInfusion') || [];
|
|
587
|
+
expect(hazOverOutgoing.length + hazOverIncoming.length).toBeGreaterThan(0);
|
|
588
|
+
});
|
|
589
|
+
it('validates infusion-pump model', async () => {
|
|
590
|
+
const source = readFileSync(PUMP_FILE, 'utf-8');
|
|
591
|
+
const doc = await parse(source);
|
|
592
|
+
const config = loadResolvedConfig(CONFIG_FILE);
|
|
593
|
+
const model = buildMemoModel([{ document: doc, filePath: 'model/infusion-pump.sysml' }], config);
|
|
594
|
+
const result = validateModel(model);
|
|
595
|
+
// Some rules should pass, some may have violations
|
|
596
|
+
expect(result.violations.length).toBeGreaterThanOrEqual(0);
|
|
597
|
+
const completeness = computeCompleteness(model, result, config);
|
|
598
|
+
expect(completeness.totalElements).toBeGreaterThan(50);
|
|
599
|
+
expect(completeness.layers.length).toBeGreaterThanOrEqual(2);
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
// ─── Dual-mode builder: registry-first resolution (M41) ─────────────────────
|
|
603
|
+
describe('Dual-mode builder with registries', () => {
|
|
604
|
+
/** Create a KindRegistry with a few test kinds */
|
|
605
|
+
function createTestKindRegistry() {
|
|
606
|
+
const kr = new KindRegistry();
|
|
607
|
+
kr.register({ name: 'Hazard', label: 'Hazard', layer: 'risk', sysmlConstruct: 'requirement def' });
|
|
608
|
+
kr.register({ name: 'RiskControl', label: 'Risk Control', layer: 'risk', sysmlConstruct: 'requirement def' });
|
|
609
|
+
kr.register({ name: 'SystemRequirement', label: 'System Req', layer: 'requirements', sysmlConstruct: 'requirement def' });
|
|
610
|
+
kr.register({ name: 'Actor', label: 'Actor', layer: 'purpose', sysmlConstruct: 'part def' });
|
|
611
|
+
kr.register({ name: 'Software', label: 'Software', layer: 'software', sysmlConstruct: 'part def' });
|
|
612
|
+
return kr;
|
|
613
|
+
}
|
|
614
|
+
/** Create a RelationshipRegistry with a few test relationship types */
|
|
615
|
+
function createTestRelRegistry() {
|
|
616
|
+
const rr = new RelationshipRegistry();
|
|
617
|
+
rr.register({ sysmlName: 'Mitigates', name: 'mitigates', label: 'Mitigates', layer: 'crosscutting', ends: [] });
|
|
618
|
+
rr.register({ sysmlName: 'TraceTo', name: 'traceTo', label: 'Trace To', layer: 'crosscutting', ends: [] });
|
|
619
|
+
return rr;
|
|
620
|
+
}
|
|
621
|
+
it('resolves kinds from registry when provided', async () => {
|
|
622
|
+
const registries = {
|
|
623
|
+
kindRegistry: createTestKindRegistry(),
|
|
624
|
+
relationshipRegistry: createTestRelRegistry(),
|
|
625
|
+
};
|
|
626
|
+
const doc = await parseDoc(`
|
|
627
|
+
package TestPkg {
|
|
628
|
+
part clinician : Actor {
|
|
629
|
+
attribute redefines name = "Clinician";
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
`);
|
|
633
|
+
// Use empty config kinds — registry should provide the resolution
|
|
634
|
+
const emptyKindsConfig = { ...testConfig, kinds: {} };
|
|
635
|
+
const model = buildMemoModel([doc], emptyKindsConfig, [], registries);
|
|
636
|
+
const el = model.elements.get('clinician');
|
|
637
|
+
expect(el).toBeDefined();
|
|
638
|
+
expect(el.kind).toBe('Actor');
|
|
639
|
+
// Registry provides 'purpose' layer instead of config's 'business'
|
|
640
|
+
expect(el.layer).toBe('purpose');
|
|
641
|
+
});
|
|
642
|
+
it('falls back to config when registry does not have the kind', async () => {
|
|
643
|
+
const registries = {
|
|
644
|
+
kindRegistry: new KindRegistry(), // empty registry
|
|
645
|
+
};
|
|
646
|
+
const doc = await parseDoc(`
|
|
647
|
+
package TestPkg {
|
|
648
|
+
part clinician : Actor {
|
|
649
|
+
attribute redefines name = "Clinician";
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
`);
|
|
653
|
+
const model = buildMemoModel([doc], testConfig, [], registries);
|
|
654
|
+
const el = model.elements.get('clinician');
|
|
655
|
+
expect(el).toBeDefined();
|
|
656
|
+
expect(el.kind).toBe('Actor');
|
|
657
|
+
expect(el.layer).toBe('business'); // from config fallback
|
|
658
|
+
});
|
|
659
|
+
it('registry takes precedence over config for same kind', async () => {
|
|
660
|
+
const kr = new KindRegistry();
|
|
661
|
+
// Register Hazard with a different layer than config
|
|
662
|
+
kr.register({ name: 'Hazard', label: 'Hazard', layer: 'safety', sysmlConstruct: 'requirement def' });
|
|
663
|
+
const registries = { kindRegistry: kr };
|
|
664
|
+
const doc = await parseDoc(`
|
|
665
|
+
package TestPkg {
|
|
666
|
+
requirement h1 : Hazard {
|
|
667
|
+
attribute redefines title = "H1";
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
`);
|
|
671
|
+
const model = buildMemoModel([doc], testConfig, [], registries);
|
|
672
|
+
const el = model.elements.get('h1');
|
|
673
|
+
expect(el.kind).toBe('Hazard');
|
|
674
|
+
// Registry's 'safety' takes precedence over config's 'risk'
|
|
675
|
+
expect(el.layer).toBe('safety');
|
|
676
|
+
});
|
|
677
|
+
it('resolves qualified type names through registry', async () => {
|
|
678
|
+
const registries = {
|
|
679
|
+
kindRegistry: createTestKindRegistry(),
|
|
680
|
+
};
|
|
681
|
+
const doc = await parseDoc(`
|
|
682
|
+
package TestPkg {
|
|
683
|
+
requirement h1 : RiskPkg::Hazard {
|
|
684
|
+
attribute redefines title = "H1";
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
`);
|
|
688
|
+
const emptyKindsConfig = { ...testConfig, kinds: {} };
|
|
689
|
+
const model = buildMemoModel([doc], emptyKindsConfig, [], registries);
|
|
690
|
+
const el = model.elements.get('h1');
|
|
691
|
+
expect(el.kind).toBe('Hazard');
|
|
692
|
+
expect(el.layer).toBe('risk');
|
|
693
|
+
});
|
|
694
|
+
it('resolves action usage kinds from registry', async () => {
|
|
695
|
+
const kr = new KindRegistry();
|
|
696
|
+
kr.register({ name: 'OperationalActivity', label: 'Op Activity', layer: 'operational', sysmlConstruct: 'action def' });
|
|
697
|
+
const registries = { kindRegistry: kr };
|
|
698
|
+
const doc = await parseDoc(`
|
|
699
|
+
package TestPkg {
|
|
700
|
+
action doSomething : OperationalActivity;
|
|
701
|
+
}
|
|
702
|
+
`);
|
|
703
|
+
const emptyKindsConfig = { ...testConfig, kinds: {} };
|
|
704
|
+
const model = buildMemoModel([doc], emptyKindsConfig, [], registries);
|
|
705
|
+
const el = model.elements.get('doSomething');
|
|
706
|
+
expect(el.kind).toBe('OperationalActivity');
|
|
707
|
+
expect(el.layer).toBe('operational');
|
|
708
|
+
});
|
|
709
|
+
it('produces identical output without registries (backward compat)', async () => {
|
|
710
|
+
const doc = await parseDoc(`
|
|
711
|
+
package TestPkg {
|
|
712
|
+
requirement rc1 : RiskControl {
|
|
713
|
+
attribute redefines title = "Control 1";
|
|
714
|
+
}
|
|
715
|
+
requirement haz1 : Hazard {
|
|
716
|
+
attribute redefines title = "Hazard 1";
|
|
717
|
+
}
|
|
718
|
+
connection : Mitigates connect control ::> rc1 to hazard ::> haz1;
|
|
719
|
+
}
|
|
720
|
+
`);
|
|
721
|
+
const modelWithout = buildMemoModel([doc], testConfig);
|
|
722
|
+
const modelWith = buildMemoModel([doc], testConfig, [], undefined);
|
|
723
|
+
expect(modelWith.elements.size).toBe(modelWithout.elements.size);
|
|
724
|
+
expect(modelWith.relationships.length).toBe(modelWithout.relationships.length);
|
|
725
|
+
expect(modelWith.elements.get('haz1')?.layer).toBe(modelWithout.elements.get('haz1')?.layer);
|
|
726
|
+
});
|
|
727
|
+
});
|
|
728
|
+
//# sourceMappingURL=builder.test.js.map
|