@documentation-robotics/cli 0.1.0 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +466 -693
- package/dist/analysis/data-model-analyzer.js +189 -0
- package/dist/analysis/data-model-analyzer.js.map +7 -0
- package/dist/analysis/index.js +3 -0
- package/dist/analysis/index.js.map +7 -0
- package/dist/analysis/relationship-classifier.js +181 -0
- package/dist/analysis/relationship-classifier.js.map +7 -0
- package/dist/analyzers/base-analyzer.js +1 -0
- package/dist/analyzers/base-analyzer.js.map +7 -0
- package/dist/analyzers/call-graph-utils.js +39 -0
- package/dist/analyzers/call-graph-utils.js.map +7 -0
- package/dist/analyzers/cbm-analyzer.js +1205 -0
- package/dist/analyzers/cbm-analyzer.js.map +7 -0
- package/dist/analyzers/heuristic-utils.js +55 -0
- package/dist/analyzers/heuristic-utils.js.map +7 -0
- package/dist/analyzers/mapping-loader.js +146 -0
- package/dist/analyzers/mapping-loader.js.map +7 -0
- package/dist/analyzers/registry.js +124 -0
- package/dist/analyzers/registry.js.map +7 -0
- package/dist/analyzers/session-state.js +176 -0
- package/dist/analyzers/session-state.js.map +7 -0
- package/dist/analyzers/stdio-client.js +208 -0
- package/dist/analyzers/stdio-client.js.map +7 -0
- package/dist/analyzers/types.js +15 -0
- package/dist/analyzers/types.js.map +7 -0
- package/dist/analyzers/verify-engine.js +209 -0
- package/dist/analyzers/verify-engine.js.map +7 -0
- package/dist/analyzers/verify-ignore.js +130 -0
- package/dist/analyzers/verify-ignore.js.map +7 -0
- package/dist/analyzers/version.js +8 -0
- package/dist/analyzers/version.js.map +7 -0
- package/dist/audit/ai/runner.js +41 -0
- package/dist/audit/ai/runner.js.map +7 -0
- package/dist/audit/differential-analyzer.js +183 -0
- package/dist/audit/differential-analyzer.js.map +7 -0
- package/dist/audit/index.js +32 -0
- package/dist/audit/index.js.map +7 -0
- package/dist/audit/nodes/ai/evaluator.js +49 -0
- package/dist/audit/nodes/ai/evaluator.js.map +7 -0
- package/dist/audit/nodes/ai/parser.js +55 -0
- package/dist/audit/nodes/ai/parser.js.map +7 -0
- package/dist/audit/nodes/ai/prompts.js +103 -0
- package/dist/audit/nodes/ai/prompts.js.map +7 -0
- package/dist/audit/nodes/analysis/node-completeness-checker.js +32 -0
- package/dist/audit/nodes/analysis/node-completeness-checker.js.map +7 -0
- package/dist/audit/nodes/analysis/node-definition-analyzer.js +47 -0
- package/dist/audit/nodes/analysis/node-definition-analyzer.js.map +7 -0
- package/dist/audit/nodes/analysis/node-overlap-detector.js +79 -0
- package/dist/audit/nodes/analysis/node-overlap-detector.js.map +7 -0
- package/dist/audit/nodes/model/orchestrator.js +82 -0
- package/dist/audit/nodes/model/orchestrator.js.map +7 -0
- package/dist/audit/nodes/spec/loader.js +116 -0
- package/dist/audit/nodes/spec/loader.js.map +7 -0
- package/dist/audit/nodes/spec/orchestrator.js +68 -0
- package/dist/audit/nodes/spec/orchestrator.js.map +7 -0
- package/dist/audit/nodes/types.js +1 -0
- package/dist/audit/nodes/types.js.map +7 -0
- package/dist/audit/pipeline/index.js +5 -0
- package/dist/audit/pipeline/index.js.map +7 -0
- package/dist/audit/pipeline/pipeline-orchestrator.js +218 -0
- package/dist/audit/pipeline/pipeline-orchestrator.js.map +7 -0
- package/dist/audit/relationships/ai/evaluator.js +235 -0
- package/dist/audit/relationships/ai/evaluator.js.map +7 -0
- package/dist/audit/relationships/ai/parser.js +197 -0
- package/dist/audit/relationships/ai/parser.js.map +7 -0
- package/dist/audit/relationships/ai/prompts.js +274 -0
- package/dist/audit/relationships/ai/prompts.js.map +7 -0
- package/dist/audit/relationships/analysis/balance-assessor.js +115 -0
- package/dist/audit/relationships/analysis/balance-assessor.js.map +7 -0
- package/dist/audit/relationships/analysis/coverage-analyzer.js +99 -0
- package/dist/audit/relationships/analysis/coverage-analyzer.js.map +7 -0
- package/dist/audit/relationships/analysis/duplicate-detector.js +95 -0
- package/dist/audit/relationships/analysis/duplicate-detector.js.map +7 -0
- package/dist/audit/relationships/analysis/gap-analyzer.js +99 -0
- package/dist/audit/relationships/analysis/gap-analyzer.js.map +7 -0
- package/dist/audit/relationships/analysis/layer-templates.js +294 -0
- package/dist/audit/relationships/analysis/layer-templates.js.map +7 -0
- package/dist/audit/relationships/graph/connectivity.js +129 -0
- package/dist/audit/relationships/graph/connectivity.js.map +7 -0
- package/dist/audit/relationships/graph/relationship-graph.js +179 -0
- package/dist/audit/relationships/graph/relationship-graph.js.map +7 -0
- package/dist/audit/relationships/model/balance-assessor.js +49 -0
- package/dist/audit/relationships/model/balance-assessor.js.map +7 -0
- package/dist/audit/relationships/model/coverage-analyzer.js +34 -0
- package/dist/audit/relationships/model/coverage-analyzer.js.map +7 -0
- package/dist/audit/relationships/model/duplicate-detector.js +68 -0
- package/dist/audit/relationships/model/duplicate-detector.js.map +7 -0
- package/dist/audit/relationships/model/gap-analyzer.js +41 -0
- package/dist/audit/relationships/model/gap-analyzer.js.map +7 -0
- package/dist/audit/relationships/model/orchestrator.js +126 -0
- package/dist/audit/relationships/model/orchestrator.js.map +7 -0
- package/dist/audit/relationships/spec/orchestrator.js +157 -0
- package/dist/audit/relationships/spec/orchestrator.js.map +7 -0
- package/dist/audit/reports/index.js +5 -0
- package/dist/audit/reports/index.js.map +7 -0
- package/dist/audit/reports/report-generator.js +118 -0
- package/dist/audit/reports/report-generator.js.map +7 -0
- package/dist/audit/snapshot-storage.js +163 -0
- package/dist/audit/snapshot-storage.js.map +7 -0
- package/dist/audit/types.js +21 -0
- package/dist/audit/types.js.map +7 -0
- package/dist/cli.js +223 -92
- package/dist/cli.js.map +3 -3
- package/dist/coding-agents/agents/claude-code.js +147 -0
- package/dist/coding-agents/agents/claude-code.js.map +7 -0
- package/dist/coding-agents/agents/index.js +5 -0
- package/dist/coding-agents/agents/index.js.map +7 -0
- package/dist/coding-agents/agents/types.js +1 -0
- package/dist/coding-agents/agents/types.js.map +7 -0
- package/dist/coding-agents/base-chat-client.js +45 -0
- package/dist/coding-agents/base-chat-client.js.map +7 -0
- package/dist/coding-agents/chat-utils.js +23 -0
- package/dist/coding-agents/chat-utils.js.map +7 -0
- package/dist/coding-agents/claude-code-client.js +246 -0
- package/dist/coding-agents/claude-code-client.js.map +7 -0
- package/dist/coding-agents/copilot-client.js +209 -0
- package/dist/coding-agents/copilot-client.js.map +7 -0
- package/dist/commands/add.js +95 -33
- package/dist/commands/add.js.map +2 -2
- package/dist/commands/analyzer.js +511 -0
- package/dist/commands/analyzer.js.map +7 -0
- package/dist/commands/audit-diff.js +49 -0
- package/dist/commands/audit-diff.js.map +7 -0
- package/dist/commands/audit-snapshots.js +62 -0
- package/dist/commands/audit-snapshots.js.map +7 -0
- package/dist/commands/audit.js +81 -0
- package/dist/commands/audit.js.map +7 -0
- package/dist/commands/catalog.js +248 -0
- package/dist/commands/catalog.js.map +7 -0
- package/dist/commands/changeset.js +577 -66
- package/dist/commands/changeset.js.map +2 -2
- package/dist/commands/chat.js +106 -83
- package/dist/commands/chat.js.map +2 -2
- package/dist/commands/claude.js +74 -0
- package/dist/commands/claude.js.map +7 -0
- package/dist/commands/conformance.js +71 -68
- package/dist/commands/conformance.js.map +2 -2
- package/dist/commands/copilot.js +75 -0
- package/dist/commands/copilot.js.map +7 -0
- package/dist/commands/delete.js +125 -11
- package/dist/commands/delete.js.map +3 -3
- package/dist/commands/discover-logic.js +44 -0
- package/dist/commands/discover-logic.js.map +7 -0
- package/dist/commands/docs.js +87 -0
- package/dist/commands/docs.js.map +7 -0
- package/dist/commands/element.js +14 -20
- package/dist/commands/element.js.map +2 -2
- package/dist/commands/export.js +13 -3
- package/dist/commands/export.js.map +2 -2
- package/dist/commands/import.js +51 -0
- package/dist/commands/import.js.map +7 -0
- package/dist/commands/info.js +30 -24
- package/dist/commands/info.js.map +2 -2
- package/dist/commands/init.js +27 -11
- package/dist/commands/init.js.map +2 -2
- package/dist/commands/list.js +63 -13
- package/dist/commands/list.js.map +3 -3
- package/dist/commands/relationship.js +225 -37
- package/dist/commands/relationship.js.map +2 -2
- package/dist/commands/report.js +54 -0
- package/dist/commands/report.js.map +7 -0
- package/dist/commands/reports.js +45 -0
- package/dist/commands/reports.js.map +7 -0
- package/dist/commands/schema.js +135 -0
- package/dist/commands/schema.js.map +7 -0
- package/dist/commands/search.js +40 -12
- package/dist/commands/search.js.map +2 -2
- package/dist/commands/show.js +58 -27
- package/dist/commands/show.js.map +2 -2
- package/dist/commands/stats.js +35 -0
- package/dist/commands/stats.js.map +7 -0
- package/dist/commands/trace.js +39 -16
- package/dist/commands/trace.js.map +2 -2
- package/dist/commands/update.js +141 -14
- package/dist/commands/update.js.map +2 -2
- package/dist/commands/upgrade.js +210 -46
- package/dist/commands/upgrade.js.map +3 -3
- package/dist/commands/validate.js +142 -23
- package/dist/commands/validate.js.map +3 -3
- package/dist/commands/version.js +8 -12
- package/dist/commands/version.js.map +2 -2
- package/dist/commands/visualize.js +162 -25
- package/dist/commands/visualize.js.map +2 -2
- package/dist/core/base-snapshot-manager.js +84 -0
- package/dist/core/base-snapshot-manager.js.map +7 -0
- package/dist/core/changeset-exporter.js +305 -0
- package/dist/core/changeset-exporter.js.map +7 -0
- package/dist/core/changeset-validator.js +41 -0
- package/dist/core/changeset-validator.js.map +7 -0
- package/dist/core/changeset.js +88 -173
- package/dist/core/changeset.js.map +2 -2
- package/dist/core/dependency-tracker.js +4 -2
- package/dist/core/dependency-tracker.js.map +2 -2
- package/dist/core/element.js +98 -27
- package/dist/core/element.js.map +2 -2
- package/dist/core/golden-copy-cache.js +290 -0
- package/dist/core/golden-copy-cache.js.map +7 -0
- package/dist/core/graph-model.js +266 -0
- package/dist/core/graph-model.js.map +7 -0
- package/dist/core/layer.js +159 -16
- package/dist/core/layer.js.map +2 -2
- package/dist/core/layers.js +32 -0
- package/dist/core/layers.js.map +7 -0
- package/dist/core/manifest.js +32 -11
- package/dist/core/manifest.js.map +2 -2
- package/dist/core/migration-registry.js +56 -1
- package/dist/core/migration-registry.js.map +2 -2
- package/dist/core/model.js +424 -217
- package/dist/core/model.js.map +3 -3
- package/dist/core/mutation-handler.js +179 -0
- package/dist/core/mutation-handler.js.map +7 -0
- package/dist/core/reference-registry.js +29 -21
- package/dist/core/reference-registry.js.map +2 -2
- package/dist/core/relationship-catalog.js +189 -0
- package/dist/core/relationship-catalog.js.map +7 -0
- package/dist/core/relationship-registry.js.map +2 -2
- package/dist/core/relationships.js.map +1 -1
- package/dist/core/report-data-model.js +285 -0
- package/dist/core/report-data-model.js.map +7 -0
- package/dist/core/spec-data-service.js +185 -0
- package/dist/core/spec-data-service.js.map +7 -0
- package/dist/core/spec-loader-types.js +1 -0
- package/dist/core/spec-loader-types.js.map +7 -0
- package/dist/core/spec-loader.js +234 -0
- package/dist/core/spec-loader.js.map +7 -0
- package/dist/core/staged-changeset-storage.js +282 -0
- package/dist/core/staged-changeset-storage.js.map +7 -0
- package/dist/core/staging-area.js +1002 -0
- package/dist/core/staging-area.js.map +7 -0
- package/dist/core/stats-collector.js +169 -0
- package/dist/core/stats-collector.js.map +7 -0
- package/dist/core/virtual-projection.js +443 -0
- package/dist/core/virtual-projection.js.map +7 -0
- package/dist/export/archimate-exporter.js +99 -60
- package/dist/export/archimate-exporter.js.map +2 -2
- package/dist/export/audit-formatters.js +479 -0
- package/dist/export/audit-formatters.js.map +7 -0
- package/dist/export/diff-formatters.js +99 -0
- package/dist/export/diff-formatters.js.map +7 -0
- package/dist/export/export-manager.js.map +2 -2
- package/dist/export/graphml-exporter.js +44 -27
- package/dist/export/graphml-exporter.js.map +2 -2
- package/dist/export/index.js +4 -0
- package/dist/export/index.js.map +2 -2
- package/dist/export/json-schema-exporter.js +55 -42
- package/dist/export/json-schema-exporter.js.map +2 -2
- package/dist/export/markdown-exporter.js +92 -70
- package/dist/export/markdown-exporter.js.map +2 -2
- package/dist/export/markdown-generator.js +248 -0
- package/dist/export/markdown-generator.js.map +7 -0
- package/dist/export/markdown-utils.js +30 -0
- package/dist/export/markdown-utils.js.map +7 -0
- package/dist/export/mermaid-markdown-exporter.js +37 -0
- package/dist/export/mermaid-markdown-exporter.js.map +7 -0
- package/dist/export/openapi-exporter.js +119 -71
- package/dist/export/openapi-exporter.js.map +2 -2
- package/dist/export/plantuml-exporter.js +104 -39
- package/dist/export/plantuml-exporter.js.map +2 -2
- package/dist/export/report-formatters.js +111 -0
- package/dist/export/report-formatters.js.map +7 -0
- package/dist/export/stats-formatters.js +98 -0
- package/dist/export/stats-formatters.js.map +7 -0
- package/dist/export/types.js +2 -14
- package/dist/export/types.js.map +2 -2
- package/dist/export/verify-formatters.js +153 -0
- package/dist/export/verify-formatters.js.map +7 -0
- package/dist/generated/compiled-validators.js +17 -0
- package/dist/generated/compiled-validators.js.map +7 -0
- package/dist/generated/index.js +31 -0
- package/dist/generated/index.js.map +7 -0
- package/dist/generated/layer-registry.js +190 -0
- package/dist/generated/layer-registry.js.map +7 -0
- package/dist/generated/layer-types.js +7 -0
- package/dist/generated/layer-types.js.map +7 -0
- package/dist/generated/node-types.js +1719 -0
- package/dist/generated/node-types.js.map +7 -0
- package/dist/generated/relationship-index.js +14552 -0
- package/dist/generated/relationship-index.js.map +7 -0
- package/dist/import/archimate-importer.js +166 -0
- package/dist/import/archimate-importer.js.map +7 -0
- package/dist/import/index.js +47 -0
- package/dist/import/index.js.map +7 -0
- package/dist/import/openapi-importer.js +143 -0
- package/dist/import/openapi-importer.js.map +7 -0
- package/dist/import/types.js +1 -0
- package/dist/import/types.js.map +7 -0
- package/dist/integrations/base-manager.js +311 -0
- package/dist/integrations/base-manager.js.map +7 -0
- package/dist/integrations/claude-manager.js +360 -0
- package/dist/integrations/claude-manager.js.map +7 -0
- package/dist/integrations/claude_code/agents/dr-advisor.md +253 -0
- package/dist/integrations/claude_code/agents/dr-architect.md +278 -0
- package/dist/integrations/claude_code/agents/dr-extractor.md +286 -0
- package/dist/integrations/claude_code/commands/dr-changeset.md +657 -0
- package/dist/integrations/claude_code/commands/dr-design.md +373 -0
- package/dist/integrations/claude_code/commands/dr-info.md +132 -0
- package/dist/integrations/claude_code/commands/dr-init.md +251 -0
- package/dist/integrations/claude_code/commands/dr-map.md +936 -0
- package/dist/integrations/claude_code/commands/dr-model.md +493 -0
- package/dist/integrations/claude_code/commands/dr-relate.md +814 -0
- package/dist/integrations/claude_code/commands/dr-sync.md +279 -0
- package/dist/integrations/claude_code/commands/dr-validate.md +654 -0
- package/dist/integrations/claude_code/commands/dr-verify.md +559 -0
- package/dist/integrations/claude_code/docs/END_TO_END_WALKTHROUGH.md +903 -0
- package/dist/integrations/claude_code/docs/QUICK_START.md +271 -0
- package/dist/integrations/claude_code/docs/README.md +347 -0
- package/dist/integrations/claude_code/skills/dr_01_motivation_layer/SKILL.md +550 -0
- package/dist/integrations/claude_code/skills/dr_02_business_layer/SKILL.md +620 -0
- package/dist/integrations/claude_code/skills/dr_03_security_layer/SKILL.md +642 -0
- package/dist/integrations/claude_code/skills/dr_04_application_layer/SKILL.md +911 -0
- package/dist/integrations/claude_code/skills/dr_05_technology_layer/SKILL.md +836 -0
- package/dist/integrations/claude_code/skills/dr_06_api_layer/SKILL.md +933 -0
- package/dist/integrations/claude_code/skills/dr_07_data_model_layer/SKILL.md +210 -0
- package/dist/integrations/claude_code/skills/dr_08_dataset_layer/SKILL.md +319 -0
- package/dist/integrations/claude_code/skills/dr_09_ux_layer/SKILL.md +319 -0
- package/dist/integrations/claude_code/skills/dr_10_navigation_layer/SKILL.md +318 -0
- package/dist/integrations/claude_code/skills/dr_11_apm_layer/SKILL.md +273 -0
- package/dist/integrations/claude_code/skills/dr_12_testing_layer/SKILL.md +273 -0
- package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +187 -0
- package/dist/integrations/claude_code/skills/dr_codebase_memory/SKILL.md +590 -0
- package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +295 -0
- package/dist/integrations/copilot-manager.js +328 -0
- package/dist/integrations/copilot-manager.js.map +7 -0
- package/dist/integrations/github_copilot/agents/dr-advisor.md +243 -0
- package/dist/integrations/github_copilot/agents/dr-architect.md +1567 -0
- package/dist/integrations/github_copilot/skills/dr_01_motivation_layer/SKILL.md +491 -0
- package/dist/integrations/github_copilot/skills/dr_02_business_layer/SKILL.md +539 -0
- package/dist/integrations/github_copilot/skills/dr_03_security_layer/SKILL.md +667 -0
- package/dist/integrations/github_copilot/skills/dr_04_application_layer/SKILL.md +670 -0
- package/dist/integrations/github_copilot/skills/dr_05_technology_layer/SKILL.md +660 -0
- package/dist/integrations/github_copilot/skills/dr_06_api_layer/SKILL.md +855 -0
- package/dist/integrations/github_copilot/skills/dr_07_data_model_layer/SKILL.md +171 -0
- package/dist/integrations/github_copilot/skills/dr_08_dataset_layer/SKILL.md +216 -0
- package/dist/integrations/github_copilot/skills/dr_09_ux_layer/SKILL.md +230 -0
- package/dist/integrations/github_copilot/skills/dr_10_navigation_layer/SKILL.md +228 -0
- package/dist/integrations/github_copilot/skills/dr_11_apm_layer/SKILL.md +234 -0
- package/dist/integrations/github_copilot/skills/dr_12_testing_layer/SKILL.md +230 -0
- package/dist/integrations/github_copilot/skills/dr_changeset_reviewer/SKILL.md +187 -0
- package/dist/integrations/hash-utils.js +51 -0
- package/dist/integrations/hash-utils.js.map +7 -0
- package/dist/integrations/types.js +16 -0
- package/dist/integrations/types.js.map +7 -0
- package/dist/reports/model-layer-report-generator.js +278 -0
- package/dist/reports/model-layer-report-generator.js.map +7 -0
- package/dist/reports/model-report-data.js +57 -0
- package/dist/reports/model-report-data.js.map +7 -0
- package/dist/reports/model-report-orchestrator.js +103 -0
- package/dist/reports/model-report-orchestrator.js.map +7 -0
- package/dist/schemas/bundled/analyzers/cbm.json +595 -0
- package/dist/schemas/bundled/analyzers/manifest.json +9 -0
- package/dist/schemas/bundled/api.json +3411 -0
- package/dist/schemas/bundled/apm.json +2371 -0
- package/dist/schemas/bundled/application.json +1253 -0
- package/dist/schemas/bundled/base.json +1622 -0
- package/dist/schemas/bundled/business.json +1279 -0
- package/dist/schemas/bundled/data-model.json +1298 -0
- package/dist/schemas/bundled/data-store.json +2025 -0
- package/dist/schemas/bundled/manifest.json +93 -0
- package/dist/schemas/bundled/motivation.json +1360 -0
- package/dist/schemas/bundled/navigation.json +1874 -0
- package/dist/schemas/bundled/security.json +3488 -0
- package/dist/schemas/bundled/technology.json +2067 -0
- package/dist/schemas/bundled/testing.json +3120 -0
- package/dist/schemas/bundled/ux.json +3592 -0
- package/dist/server/schemas.js +202 -0
- package/dist/server/schemas.js.map +7 -0
- package/dist/server/server.js +1336 -252
- package/dist/server/server.js.map +3 -3
- package/dist/server/telemetry-middleware.js +22 -15
- package/dist/server/telemetry-middleware.js.map +2 -2
- package/dist/server-entry.js +65 -0
- package/dist/server-entry.js.map +7 -0
- package/dist/telemetry/config.js +89 -0
- package/dist/telemetry/config.js.map +7 -0
- package/dist/telemetry/console-interceptor.js.map +1 -1
- package/dist/telemetry/detect.js +24 -0
- package/dist/telemetry/detect.js.map +7 -0
- package/dist/telemetry/fetch-otlp-exporter.js +112 -0
- package/dist/telemetry/fetch-otlp-exporter.js.map +7 -0
- package/dist/telemetry/index.js +153 -3
- package/dist/telemetry/index.js.map +2 -2
- package/dist/telemetry/resilient-exporter.js +22 -8
- package/dist/telemetry/resilient-exporter.js.map +2 -2
- package/dist/telemetry/resilient-log-exporter.js +17 -8
- package/dist/telemetry/resilient-log-exporter.js.map +2 -2
- package/dist/telemetry/test-instrumentation.js.map +2 -2
- package/dist/types/index.js +84 -0
- package/dist/types/index.js.map +3 -3
- package/dist/types/source-reference.js +1 -0
- package/dist/types/source-reference.js.map +7 -0
- package/dist/utils/chat-logger.js +292 -0
- package/dist/utils/chat-logger.js.map +7 -0
- package/dist/utils/claude-stream.js +8 -0
- package/dist/utils/claude-stream.js.map +7 -0
- package/dist/utils/date-utils.js +7 -0
- package/dist/utils/date-utils.js.map +7 -0
- package/dist/utils/element-utils.js.map +1 -1
- package/dist/utils/errors.js +88 -15
- package/dist/utils/errors.js.map +3 -3
- package/dist/utils/export-python-annotations.js +82 -0
- package/dist/utils/export-python-annotations.js.map +7 -0
- package/dist/utils/file-io.js +7 -2
- package/dist/utils/file-io.js.map +2 -2
- package/dist/utils/file-lock.js +156 -0
- package/dist/utils/file-lock.js.map +7 -0
- package/dist/utils/id-generator.js +18 -0
- package/dist/utils/id-generator.js.map +7 -0
- package/dist/utils/layer-name-formatter.js +16 -0
- package/dist/utils/layer-name-formatter.js.map +7 -0
- package/dist/utils/markdown-anchor.js +7 -0
- package/dist/utils/markdown-anchor.js.map +7 -0
- package/dist/utils/markdown-link.js +12 -0
- package/dist/utils/markdown-link.js.map +7 -0
- package/dist/utils/markdown-table.js +17 -0
- package/dist/utils/markdown-table.js.map +7 -0
- package/dist/utils/mermaid-utils.js +11 -0
- package/dist/utils/mermaid-utils.js.map +7 -0
- package/dist/utils/project-paths.js.map +2 -2
- package/dist/utils/source-reference.js +52 -0
- package/dist/utils/source-reference.js.map +7 -0
- package/dist/utils/spec-installer.js +40 -53
- package/dist/utils/spec-installer.js.map +2 -2
- package/dist/utils/spec-version.js +5 -1
- package/dist/utils/spec-version.js.map +2 -2
- package/dist/utils/string-utils.js +12 -0
- package/dist/utils/string-utils.js.map +7 -0
- package/dist/utils/table-formatting.js +19 -0
- package/dist/utils/table-formatting.js.map +7 -0
- package/dist/validators/index.js +4 -0
- package/dist/validators/index.js.map +2 -2
- package/dist/validators/naming-validator.js +20 -23
- package/dist/validators/naming-validator.js.map +2 -2
- package/dist/validators/reference-validator.js +23 -38
- package/dist/validators/reference-validator.js.map +2 -2
- package/dist/validators/relationship-schema-validator.js +243 -0
- package/dist/validators/relationship-schema-validator.js.map +7 -0
- package/dist/validators/schema-validator.js +168 -68
- package/dist/validators/schema-validator.js.map +2 -2
- package/dist/validators/semantic-validator.js +36 -60
- package/dist/validators/semantic-validator.js.map +2 -2
- package/dist/validators/types.js.map +2 -2
- package/dist/validators/validation-formatter.js +159 -0
- package/dist/validators/validation-formatter.js.map +7 -0
- package/dist/validators/validator.js +24 -38
- package/dist/validators/validator.js.map +2 -2
- package/dist/viewer/README.md +139 -0
- package/dist/viewer/assets/main-CY0Xufuj.css +1 -0
- package/dist/viewer/assets/main-DtgErnwF.js +81 -0
- package/dist/viewer/assets/vendor-CxKvDp2x.js +17 -0
- package/dist/viewer/favicon.svg +11 -0
- package/dist/viewer/fonts/inter/Inter-Black.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Bold.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-ExtraBold.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Light.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Medium.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-Regular.woff2 +0 -0
- package/dist/viewer/fonts/inter/Inter-SemiBold.woff2 +0 -0
- package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2 +0 -0
- package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
- package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2 +0 -0
- package/dist/viewer/index.html +15 -0
- package/dist/viewer/manifest.json +99 -0
- package/dist/viewer/version.json +1 -0
- package/package.json +42 -16
- package/PYTHON_CLI_PARITY.md +0 -265
- package/PYTHON_CLI_STRUCTURE_UPDATE.md +0 -246
- package/biome.json +0 -42
- package/bunfig.toml +0 -3
- package/dist/ai/claude-client.js +0 -71
- package/dist/ai/claude-client.js.map +0 -7
- package/dist/ai/context-provider.js +0 -129
- package/dist/ai/context-provider.js.map +0 -7
- package/dist/ai/tools.js +0 -231
- package/dist/ai/tools.js.map +0 -7
- package/dist/commands/migrate.js +0 -36
- package/dist/commands/migrate.js.map +0 -7
- package/dist/commands/project.js +0 -74
- package/dist/commands/project.js.map +0 -7
- package/dist/core/active-changeset.js +0 -52
- package/dist/core/active-changeset.js.map +0 -7
- package/dist/core/projection-engine.js +0 -288
- package/dist/core/projection-engine.js.map +0 -7
- package/dist/schemas/bundled/01-motivation-layer.schema.json +0 -942
- package/dist/schemas/bundled/02-business-layer.schema.json +0 -1293
- package/dist/schemas/bundled/03-security-layer.schema.json +0 -2177
- package/dist/schemas/bundled/04-application-layer.schema.json +0 -1328
- package/dist/schemas/bundled/05-technology-layer.schema.json +0 -1465
- package/dist/schemas/bundled/06-api-layer.schema.json +0 -1743
- package/dist/schemas/bundled/07-data-model-layer.schema.json +0 -1253
- package/dist/schemas/bundled/08-datastore-layer.schema.json +0 -892
- package/dist/schemas/bundled/09-ux-layer.schema.json +0 -1506
- package/dist/schemas/bundled/10-navigation-layer.schema.json +0 -843
- package/dist/schemas/bundled/11-apm-observability-layer.schema.json +0 -1430
- package/dist/schemas/bundled/12-testing-layer.schema.json +0 -1091
- package/dist/schemas/bundled/common/layer-extensions.schema.json +0 -266
- package/dist/schemas/bundled/common/predicates.schema.json +0 -493
- package/dist/schemas/bundled/common/relationships.schema.json +0 -791
- package/dist/schemas/bundled/common/source-references.schema.json +0 -71
- package/dist/schemas/bundled/link-registry.json +0 -1839
- package/dist/schemas/bundled/link-registry.schema.json +0 -339
- package/dist/schemas/bundled/relationship-catalog.json +0 -1302
- package/dist/schemas/bundled/relationship-type.schema.json +0 -221
- package/dist/utils/model-path.js +0 -22
- package/dist/utils/model-path.js.map +0 -7
- package/docs/TEST-INSTRUMENTATION.md +0 -405
- package/docs/telemetry.md +0 -427
- package/test-debug.js +0 -33
- package/test-special.mjs +0 -46
- package/test_runner.ts +0 -7
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
class DataModelAnalyzer {
|
|
2
|
+
model;
|
|
3
|
+
constructor(model) {
|
|
4
|
+
this.model = model;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Analyze entities in the data model layer
|
|
8
|
+
*/
|
|
9
|
+
async analyzeEntities() {
|
|
10
|
+
const dataModelLayer = await this.model.getLayer("data-model"), entities = [];
|
|
11
|
+
if (!dataModelLayer)
|
|
12
|
+
return entities;
|
|
13
|
+
const referencesFrom = /* @__PURE__ */ new Set();
|
|
14
|
+
for (const layerName of this.model.getLayerNames()) {
|
|
15
|
+
if (layerName === "data-model")
|
|
16
|
+
continue;
|
|
17
|
+
const layer = await this.model.getLayer(layerName);
|
|
18
|
+
if (layer) {
|
|
19
|
+
for (const element of layer.listElements())
|
|
20
|
+
if (element.references)
|
|
21
|
+
for (const ref of element.references)
|
|
22
|
+
ref.target.startsWith("data-model.") && referencesFrom.add(ref.target);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
for (const element of dataModelLayer.listElements()) {
|
|
26
|
+
const attributes = element.attributes ? Object.keys(element.attributes) : [], relationships = element.relationships ? element.relationships : [];
|
|
27
|
+
entities.push({
|
|
28
|
+
id: element.path || element.id || "",
|
|
29
|
+
name: element.name,
|
|
30
|
+
layer: "data-model",
|
|
31
|
+
attributes,
|
|
32
|
+
relatedEntities: relationships.map((r) => r.target),
|
|
33
|
+
isReferenced: referencesFrom.has(element.path || element.id || "")
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return entities;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check constraints for data model entities
|
|
40
|
+
*/
|
|
41
|
+
async checkConstraints() {
|
|
42
|
+
const dataModelLayer = await this.model.getLayer("data-model"), constraints = [];
|
|
43
|
+
if (!dataModelLayer)
|
|
44
|
+
return constraints;
|
|
45
|
+
for (const element of dataModelLayer.listElements())
|
|
46
|
+
(!element.attributes || Object.keys(element.attributes).length === 0) && constraints.push({
|
|
47
|
+
entityId: element.path || element.id || "",
|
|
48
|
+
constraintType: "not-null",
|
|
49
|
+
description: "Entity has no attributes defined",
|
|
50
|
+
isValid: !1
|
|
51
|
+
}), (!element.description || element.description.length === 0) && constraints.push({
|
|
52
|
+
entityId: element.path || element.id || "",
|
|
53
|
+
constraintType: "check",
|
|
54
|
+
description: "Entity has no description",
|
|
55
|
+
isValid: !1
|
|
56
|
+
});
|
|
57
|
+
return constraints;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Analyze cardinality of relationships
|
|
61
|
+
*/
|
|
62
|
+
async checkCardinality() {
|
|
63
|
+
const dataModelLayer = await this.model.getLayer("data-model"), cardinalities = [];
|
|
64
|
+
if (!dataModelLayer)
|
|
65
|
+
return cardinalities;
|
|
66
|
+
for (const element of dataModelLayer.listElements())
|
|
67
|
+
if (element.relationships)
|
|
68
|
+
for (const rel of element.relationships) {
|
|
69
|
+
let cardinality = "one-to-many";
|
|
70
|
+
rel.predicate.includes("one-to-one") || rel.predicate === "has-one" ? cardinality = "one-to-one" : (rel.predicate.includes("many-to-many") || rel.predicate === "has-many-to-many") && (cardinality = "many-to-many"), cardinalities.push({
|
|
71
|
+
sourceEntity: element.path || element.id || "",
|
|
72
|
+
targetEntity: rel.target,
|
|
73
|
+
cardinality,
|
|
74
|
+
isOptional: rel.properties?.optional === !0 || !1
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return cardinalities;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Find data quality issues
|
|
81
|
+
*/
|
|
82
|
+
async identifyIssues() {
|
|
83
|
+
const issues = [], entities = await this.analyzeEntities(), constraints = await this.checkConstraints();
|
|
84
|
+
for (const constraint of constraints)
|
|
85
|
+
constraint.isValid || issues.push({
|
|
86
|
+
type: constraint.constraintType === "not-null" ? "incomplete" : "missing-constraint",
|
|
87
|
+
entityId: constraint.entityId,
|
|
88
|
+
description: constraint.description,
|
|
89
|
+
severity: "medium"
|
|
90
|
+
});
|
|
91
|
+
for (const entity of entities)
|
|
92
|
+
!entity.isReferenced && entity.relatedEntities.length === 0 && issues.push({
|
|
93
|
+
type: "orphaned",
|
|
94
|
+
entityId: entity.id,
|
|
95
|
+
description: `Entity "${entity.name}" is not referenced and has no relationships`,
|
|
96
|
+
severity: "low"
|
|
97
|
+
});
|
|
98
|
+
return issues;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Calculate coverage metrics
|
|
102
|
+
*/
|
|
103
|
+
async calculateCoverage() {
|
|
104
|
+
const entities = await this.analyzeEntities();
|
|
105
|
+
let documentsCount = 0, constraintCount = 0, referencedCount = 0, orphanedCount = 0;
|
|
106
|
+
for (const entity of entities)
|
|
107
|
+
entity.attributes && entity.attributes.length > 0 && documentsCount++, entity.isReferenced && referencedCount++, !entity.isReferenced && entity.relatedEntities.length === 0 && orphanedCount++, entity.attributes && entity.attributes.length > 0 && constraintCount++;
|
|
108
|
+
const totalEntities = entities.length;
|
|
109
|
+
return {
|
|
110
|
+
totalEntities,
|
|
111
|
+
entitiesWithAttributes: documentsCount,
|
|
112
|
+
constraintsEntities: constraintCount,
|
|
113
|
+
referencedEntities: referencedCount,
|
|
114
|
+
orphanedEntities: orphanedCount,
|
|
115
|
+
attributeCoverage: totalEntities > 0 ? Math.round(documentsCount / totalEntities * 100) : 0,
|
|
116
|
+
constraintCoverage: totalEntities > 0 ? Math.round(constraintCount / totalEntities * 100) : 0,
|
|
117
|
+
referenceCoverage: totalEntities > 0 ? Math.round(referencedCount / totalEntities * 100) : 0
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Calculate complexity metrics
|
|
122
|
+
*/
|
|
123
|
+
async calculateComplexity() {
|
|
124
|
+
const entities = await this.analyzeEntities();
|
|
125
|
+
if (entities.length === 0)
|
|
126
|
+
return {
|
|
127
|
+
avgAttributesPerEntity: 0,
|
|
128
|
+
maxAttributesPerEntity: 0,
|
|
129
|
+
minAttributesPerEntity: 0,
|
|
130
|
+
avgRelationshipsPerEntity: 0,
|
|
131
|
+
maxRelationshipsPerEntity: 0,
|
|
132
|
+
entityDensity: 0
|
|
133
|
+
};
|
|
134
|
+
let totalAttributes = 0, maxAttributes = 0, minAttributes = 1 / 0, totalRelationships = 0, maxRelationships = 0;
|
|
135
|
+
for (const entity of entities) {
|
|
136
|
+
const attrCount = entity.attributes.length, relCount = entity.relatedEntities.length;
|
|
137
|
+
totalAttributes += attrCount, totalRelationships += relCount, maxAttributes = Math.max(maxAttributes, attrCount), minAttributes = Math.min(minAttributes, attrCount), maxRelationships = Math.max(maxRelationships, relCount);
|
|
138
|
+
}
|
|
139
|
+
const avgAttributes = totalAttributes / entities.length, avgRelationships = totalRelationships / entities.length, density = entities.length > 0 ? totalRelationships / (entities.length * entities.length) : 0;
|
|
140
|
+
return {
|
|
141
|
+
avgAttributesPerEntity: Math.round(avgAttributes * 10) / 10,
|
|
142
|
+
maxAttributesPerEntity: maxAttributes,
|
|
143
|
+
minAttributesPerEntity: minAttributes === 1 / 0 ? 0 : minAttributes,
|
|
144
|
+
avgRelationshipsPerEntity: Math.round(avgRelationships * 10) / 10,
|
|
145
|
+
maxRelationshipsPerEntity: maxRelationships,
|
|
146
|
+
entityDensity: Math.round(density * 1e4) / 1e4
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get entity dependency graph
|
|
151
|
+
*/
|
|
152
|
+
async getEntityDependencyGraph() {
|
|
153
|
+
const entities = await this.analyzeEntities(), graph = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const entity of entities) {
|
|
155
|
+
graph.has(entity.id) || graph.set(entity.id, /* @__PURE__ */ new Set());
|
|
156
|
+
for (const relatedId of entity.relatedEntities)
|
|
157
|
+
graph.get(entity.id).add(relatedId);
|
|
158
|
+
}
|
|
159
|
+
return graph;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Find entity clusters based on relationships
|
|
163
|
+
*/
|
|
164
|
+
async findClusters() {
|
|
165
|
+
const graph = await this.getEntityDependencyGraph(), visited = /* @__PURE__ */ new Set(), clusters = [];
|
|
166
|
+
for (const nodeId of graph.keys())
|
|
167
|
+
if (!visited.has(nodeId)) {
|
|
168
|
+
const cluster = /* @__PURE__ */ new Set();
|
|
169
|
+
this.dfsCluster(nodeId, graph, visited, cluster), clusters.push(cluster);
|
|
170
|
+
}
|
|
171
|
+
return clusters;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* DFS to find connected components (clusters)
|
|
175
|
+
*/
|
|
176
|
+
dfsCluster(nodeId, graph, visited, cluster) {
|
|
177
|
+
if (visited.has(nodeId))
|
|
178
|
+
return;
|
|
179
|
+
visited.add(nodeId), cluster.add(nodeId);
|
|
180
|
+
const neighbors = graph.get(nodeId);
|
|
181
|
+
if (neighbors)
|
|
182
|
+
for (const neighbor of neighbors)
|
|
183
|
+
this.dfsCluster(neighbor, graph, visited, cluster);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
export {
|
|
187
|
+
DataModelAnalyzer
|
|
188
|
+
};
|
|
189
|
+
//# sourceMappingURL=data-model-analyzer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/analysis/data-model-analyzer.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Data Model Analyzer - Layer 7 specific analysis\n *\n * Provides specialized analysis for the Data Model layer (Layer 7).\n * Analyzes entities, relationships, constraints, and data quality.\n */\n\nimport { Model } from \"../core/model.js\";\nimport { DataModelEntity } from \"../core/report-data-model.js\";\n\n/**\n * Entity constraint information\n */\nexport interface EntityConstraint {\n entityId: string;\n constraintType: \"primary-key\" | \"unique\" | \"not-null\" | \"foreign-key\" | \"check\";\n description: string;\n isValid: boolean;\n}\n\n/**\n * Cardinality information\n */\nexport interface CardinalityInfo {\n sourceEntity: string;\n targetEntity: string;\n cardinality: \"one-to-one\" | \"one-to-many\" | \"many-to-many\";\n isOptional: boolean;\n}\n\n/**\n * Data quality issue\n */\nexport interface DataQualityIssue {\n type: \"incomplete\" | \"inconsistent\" | \"orphaned\" | \"invalid-reference\" | \"missing-constraint\";\n entityId: string;\n description: string;\n severity: \"low\" | \"medium\" | \"high\";\n}\n\n/**\n * Entity relationship information\n */\nexport interface EntityRelationship {\n source: string;\n target: string;\n cardinality: string;\n type: string;\n}\n\n/**\n * Coverage metrics for data model\n */\nexport interface DataModelCoverageMetrics {\n totalEntities: number;\n entitiesWithAttributes: number;\n constraintsEntities: number;\n referencedEntities: number;\n orphanedEntities: number;\n attributeCoverage: number; // 0-100\n constraintCoverage: number; // 0-100\n referenceCoverage: number; // 0-100\n}\n\n/**\n * Data model complexity metrics\n */\nexport interface DataModelComplexityMetrics {\n avgAttributesPerEntity: number;\n maxAttributesPerEntity: number;\n minAttributesPerEntity: number;\n avgRelationshipsPerEntity: number;\n maxRelationshipsPerEntity: number;\n entityDensity: number; // Relationships per entity squared\n}\n\n/**\n * Data Model Analyzer\n */\nexport class DataModelAnalyzer {\n constructor(private model: Model) {}\n\n /**\n * Analyze entities in the data model layer\n */\n async analyzeEntities(): Promise<DataModelEntity[]> {\n const dataModelLayer = await this.model.getLayer(\"data-model\");\n const entities: DataModelEntity[] = [];\n\n if (!dataModelLayer) {\n return entities;\n }\n\n // Get all references to data model entities from other layers\n const referencesFrom = new Set<string>();\n for (const layerName of this.model.getLayerNames()) {\n if (layerName === \"data-model\") continue;\n const layer = await this.model.getLayer(layerName);\n if (!layer) continue;\n\n for (const element of layer.listElements()) {\n if (element.references) {\n for (const ref of element.references) {\n if (ref.target.startsWith(\"data-model.\")) {\n referencesFrom.add(ref.target);\n }\n }\n }\n }\n }\n\n // Analyze each entity\n for (const element of dataModelLayer.listElements()) {\n const attributes = element.attributes ? Object.keys(element.attributes) : [];\n const relationships = element.relationships ? element.relationships : [];\n\n entities.push({\n id: element.path || element.id || \"\",\n name: element.name,\n layer: \"data-model\",\n attributes,\n relatedEntities: relationships.map((r) => r.target),\n isReferenced: referencesFrom.has(element.path || element.id || \"\"),\n });\n }\n\n return entities;\n }\n\n /**\n * Check constraints for data model entities\n */\n async checkConstraints(): Promise<EntityConstraint[]> {\n const dataModelLayer = await this.model.getLayer(\"data-model\");\n const constraints: EntityConstraint[] = [];\n\n if (!dataModelLayer) {\n return constraints;\n }\n\n for (const element of dataModelLayer.listElements()) {\n // Check if element has attributes\n if (!element.attributes || Object.keys(element.attributes).length === 0) {\n constraints.push({\n entityId: element.path || element.id || \"\",\n constraintType: \"not-null\",\n description: \"Entity has no attributes defined\",\n isValid: false,\n });\n }\n\n // Check if entity is documented\n if (!element.description || element.description.length === 0) {\n constraints.push({\n entityId: element.path || element.id || \"\",\n constraintType: \"check\",\n description: \"Entity has no description\",\n isValid: false,\n });\n }\n }\n\n return constraints;\n }\n\n /**\n * Analyze cardinality of relationships\n */\n async checkCardinality(): Promise<CardinalityInfo[]> {\n const dataModelLayer = await this.model.getLayer(\"data-model\");\n const cardinalities: CardinalityInfo[] = [];\n\n if (!dataModelLayer) {\n return cardinalities;\n }\n\n for (const element of dataModelLayer.listElements()) {\n if (!element.relationships) continue;\n\n for (const rel of element.relationships) {\n // Infer cardinality from relationship properties or attributes\n let cardinality: \"one-to-one\" | \"one-to-many\" | \"many-to-many\" = \"one-to-many\";\n\n // Simple heuristic: if predicate contains \"many\", it's many-to-many or one-to-many\n if (rel.predicate.includes(\"one-to-one\") || rel.predicate === \"has-one\") {\n cardinality = \"one-to-one\";\n } else if (rel.predicate.includes(\"many-to-many\") || rel.predicate === \"has-many-to-many\") {\n cardinality = \"many-to-many\";\n }\n\n cardinalities.push({\n sourceEntity: element.path || element.id || \"\",\n targetEntity: rel.target,\n cardinality,\n isOptional: rel.properties?.optional === true || false,\n });\n }\n }\n\n return cardinalities;\n }\n\n /**\n * Find data quality issues\n */\n async identifyIssues(): Promise<DataQualityIssue[]> {\n const issues: DataQualityIssue[] = [];\n const entities = await this.analyzeEntities();\n const constraints = await this.checkConstraints();\n\n // Add constraint issues\n for (const constraint of constraints) {\n if (!constraint.isValid) {\n issues.push({\n type: constraint.constraintType === \"not-null\" ? \"incomplete\" : \"missing-constraint\",\n entityId: constraint.entityId,\n description: constraint.description,\n severity: \"medium\",\n });\n }\n }\n\n // Find orphaned entities\n for (const entity of entities) {\n if (!entity.isReferenced && entity.relatedEntities.length === 0) {\n issues.push({\n type: \"orphaned\",\n entityId: entity.id,\n description: `Entity \"${entity.name}\" is not referenced and has no relationships`,\n severity: \"low\",\n });\n }\n }\n\n return issues;\n }\n\n /**\n * Calculate coverage metrics\n */\n async calculateCoverage(): Promise<DataModelCoverageMetrics> {\n const entities = await this.analyzeEntities();\n\n let documentsCount = 0;\n let constraintCount = 0;\n let referencedCount = 0;\n let orphanedCount = 0;\n\n for (const entity of entities) {\n if (entity.attributes && entity.attributes.length > 0) {\n documentsCount++;\n }\n\n if (entity.isReferenced) {\n referencedCount++;\n }\n\n if (!entity.isReferenced && entity.relatedEntities.length === 0) {\n orphanedCount++;\n }\n\n // Simple heuristic for constraints: if entity has attributes\n if (entity.attributes && entity.attributes.length > 0) {\n constraintCount++;\n }\n }\n\n const totalEntities = entities.length;\n\n return {\n totalEntities,\n entitiesWithAttributes: documentsCount,\n constraintsEntities: constraintCount,\n referencedEntities: referencedCount,\n orphanedEntities: orphanedCount,\n attributeCoverage:\n totalEntities > 0 ? Math.round((documentsCount / totalEntities) * 100) : 0,\n constraintCoverage: totalEntities > 0 ? Math.round((constraintCount / totalEntities) * 100) : 0,\n referenceCoverage: totalEntities > 0 ? Math.round((referencedCount / totalEntities) * 100) : 0,\n };\n }\n\n /**\n * Calculate complexity metrics\n */\n async calculateComplexity(): Promise<DataModelComplexityMetrics> {\n const entities = await this.analyzeEntities();\n\n if (entities.length === 0) {\n return {\n avgAttributesPerEntity: 0,\n maxAttributesPerEntity: 0,\n minAttributesPerEntity: 0,\n avgRelationshipsPerEntity: 0,\n maxRelationshipsPerEntity: 0,\n entityDensity: 0,\n };\n }\n\n let totalAttributes = 0;\n let maxAttributes = 0;\n let minAttributes = Infinity;\n let totalRelationships = 0;\n let maxRelationships = 0;\n\n for (const entity of entities) {\n const attrCount = entity.attributes.length;\n const relCount = entity.relatedEntities.length;\n\n totalAttributes += attrCount;\n totalRelationships += relCount;\n\n maxAttributes = Math.max(maxAttributes, attrCount);\n minAttributes = Math.min(minAttributes, attrCount);\n maxRelationships = Math.max(maxRelationships, relCount);\n }\n\n const avgAttributes = totalAttributes / entities.length;\n const avgRelationships = totalRelationships / entities.length;\n const density =\n entities.length > 0\n ? totalRelationships / (entities.length * entities.length)\n : 0;\n\n return {\n avgAttributesPerEntity: Math.round(avgAttributes * 10) / 10,\n maxAttributesPerEntity: maxAttributes,\n minAttributesPerEntity: minAttributes === Infinity ? 0 : minAttributes,\n avgRelationshipsPerEntity: Math.round(avgRelationships * 10) / 10,\n maxRelationshipsPerEntity: maxRelationships,\n entityDensity: Math.round(density * 10000) / 10000,\n };\n }\n\n /**\n * Get entity dependency graph\n */\n async getEntityDependencyGraph(): Promise<Map<string, Set<string>>> {\n const entities = await this.analyzeEntities();\n const graph = new Map<string, Set<string>>();\n\n for (const entity of entities) {\n if (!graph.has(entity.id)) {\n graph.set(entity.id, new Set());\n }\n\n for (const relatedId of entity.relatedEntities) {\n const deps = graph.get(entity.id)!;\n deps.add(relatedId);\n }\n }\n\n return graph;\n }\n\n /**\n * Find entity clusters based on relationships\n */\n async findClusters(): Promise<Set<string>[]> {\n const graph = await this.getEntityDependencyGraph();\n const visited = new Set<string>();\n const clusters: Set<string>[] = [];\n\n for (const nodeId of graph.keys()) {\n if (!visited.has(nodeId)) {\n const cluster = new Set<string>();\n this.dfsCluster(nodeId, graph, visited, cluster);\n clusters.push(cluster);\n }\n }\n\n return clusters;\n }\n\n /**\n * DFS to find connected components (clusters)\n */\n private dfsCluster(\n nodeId: string,\n graph: Map<string, Set<string>>,\n visited: Set<string>,\n cluster: Set<string>\n ): void {\n if (visited.has(nodeId)) {\n return;\n }\n\n visited.add(nodeId);\n cluster.add(nodeId);\n\n const neighbors = graph.get(nodeId);\n if (neighbors) {\n for (const neighbor of neighbors) {\n this.dfsCluster(neighbor, graph, visited, cluster);\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/analysis/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Analysis module - Semantic relationship and data model analysis\n */\n\nexport * from \"./relationship-classifier.js\";\nexport * from \"./data-model-analyzer.js\";\n"],
|
|
5
|
+
"mappings": "AAIA,cAAc;AACd,cAAc;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { getLayerOrder, isValidLayerName } from "../core/layers.js";
|
|
2
|
+
var RelationshipStrength;
|
|
3
|
+
(function(RelationshipStrength2) {
|
|
4
|
+
RelationshipStrength2.Weak = "weak", RelationshipStrength2.Medium = "medium", RelationshipStrength2.Strong = "strong";
|
|
5
|
+
})(RelationshipStrength || (RelationshipStrength = {}));
|
|
6
|
+
class RelationshipClassifier {
|
|
7
|
+
catalog;
|
|
8
|
+
relationshipTypeMap = /* @__PURE__ */ new Map();
|
|
9
|
+
catalogLoaded = !1;
|
|
10
|
+
constructor(catalog) {
|
|
11
|
+
this.catalog = catalog;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load and prepare the catalog
|
|
15
|
+
*/
|
|
16
|
+
async load() {
|
|
17
|
+
if (this.catalogLoaded)
|
|
18
|
+
return;
|
|
19
|
+
await this.catalog.load();
|
|
20
|
+
const types = this.catalog.getAllTypes();
|
|
21
|
+
for (const type of types)
|
|
22
|
+
this.relationshipTypeMap.set(type.predicate, type);
|
|
23
|
+
this.catalogLoaded = !0;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Classify a single relationship with detailed semantic information
|
|
27
|
+
*/
|
|
28
|
+
async classify(rel, relationshipId) {
|
|
29
|
+
await this.load();
|
|
30
|
+
const sourceLayer = rel.source.split(".")[0], targetLayer = rel.target.split(".")[0], isCrossLayer = sourceLayer !== targetLayer, relationshipType = this.relationshipTypeMap.get(rel.predicate);
|
|
31
|
+
return {
|
|
32
|
+
id: relationshipId || `${rel.source}\u2192${rel.predicate}\u2192${rel.target}`,
|
|
33
|
+
source: rel.source,
|
|
34
|
+
target: rel.target,
|
|
35
|
+
predicate: rel.predicate,
|
|
36
|
+
category: relationshipType?.category || "unknown",
|
|
37
|
+
archimateAlignment: relationshipType?.archimateAlignment || null,
|
|
38
|
+
directionality: relationshipType?.semantics?.directionality || "unidirectional",
|
|
39
|
+
transitivity: relationshipType?.semantics?.transitivity || !1,
|
|
40
|
+
symmetry: relationshipType?.semantics?.symmetry || !1,
|
|
41
|
+
reflexivity: relationshipType?.semantics?.reflexivity,
|
|
42
|
+
sourceLayer,
|
|
43
|
+
targetLayer,
|
|
44
|
+
isCrossLayer,
|
|
45
|
+
isSpecCompliant: relationshipType !== void 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Classify a batch of relationships
|
|
50
|
+
*/
|
|
51
|
+
async classifyBatch(relationships) {
|
|
52
|
+
const classified = [];
|
|
53
|
+
for (let i = 0; i < relationships.length; i++) {
|
|
54
|
+
const rel = relationships[i], relationshipId = `${rel.source}\u2192${rel.predicate}\u2192${rel.target}`, classifiedRel = await this.classify(rel, relationshipId);
|
|
55
|
+
classified.push(classifiedRel);
|
|
56
|
+
}
|
|
57
|
+
return classified;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get relationship breakdown by category
|
|
61
|
+
*/
|
|
62
|
+
async getCategoryBreakdown(relationships) {
|
|
63
|
+
const byCategory = {};
|
|
64
|
+
for (const rel of relationships)
|
|
65
|
+
byCategory[rel.category] || (byCategory[rel.category] = []), byCategory[rel.category].push(rel);
|
|
66
|
+
const breakdown = [];
|
|
67
|
+
for (const [category, rels] of Object.entries(byCategory)) {
|
|
68
|
+
const predicates = Array.from(new Set(rels.map((r) => r.predicate))), avgStrength = this.calculateAverageStrength(rels);
|
|
69
|
+
breakdown.push({
|
|
70
|
+
category,
|
|
71
|
+
count: rels.length,
|
|
72
|
+
percentage: rels.length / relationships.length * 100,
|
|
73
|
+
predicates,
|
|
74
|
+
avgStrength
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return breakdown.sort((a, b) => b.count - a.count);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Analyze transitive relationships for a specific predicate
|
|
81
|
+
*/
|
|
82
|
+
async analyzeTransitivity(relationships, predicate) {
|
|
83
|
+
const isTransitive = this.relationshipTypeMap.get(predicate)?.semantics.transitivity || !1, chains = [];
|
|
84
|
+
if (isTransitive) {
|
|
85
|
+
const relsByPredicate = relationships.filter((r) => r.predicate === predicate);
|
|
86
|
+
for (const rel1 of relsByPredicate)
|
|
87
|
+
for (const rel2 of relsByPredicate)
|
|
88
|
+
rel1.target === rel2.source && rel1.source !== rel2.target && chains.push({
|
|
89
|
+
elements: [rel1.source, rel1.target, rel2.target],
|
|
90
|
+
pathLength: 2
|
|
91
|
+
});
|
|
92
|
+
const uniqueChains = Array.from(new Map(chains.map((c) => [c.elements.join("\u2192"), c])).values());
|
|
93
|
+
return {
|
|
94
|
+
predicate,
|
|
95
|
+
isTransitive: !0,
|
|
96
|
+
chains: uniqueChains
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
predicate,
|
|
101
|
+
isTransitive: !1,
|
|
102
|
+
chains: []
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Validate a relationship against semantic rules
|
|
107
|
+
*/
|
|
108
|
+
async validateSemantics(rel) {
|
|
109
|
+
await this.load();
|
|
110
|
+
const issues = [], warnings = [], relationshipType = this.relationshipTypeMap.get(rel.predicate);
|
|
111
|
+
return relationshipType ? (!relationshipType.semantics.reflexivity && rel.source === rel.target && issues.push(`Predicate "${rel.predicate}" does not support reflexive relationships`), relationshipType.semantics.symmetry && rel.directionality === "unidirectional" && warnings.push(`Predicate "${rel.predicate}" is symmetric but may be unidirectional`), rel.isCrossLayer && (!isValidLayerName(rel.sourceLayer) || !isValidLayerName(rel.targetLayer) ? warnings.push(`Cross-layer relationship references unknown layer(s): ${rel.sourceLayer} \u2192 ${rel.targetLayer}`) : this.getLayerOrder(rel.sourceLayer, rel.targetLayer) < 0 && warnings.push(`Cross-layer relationship violates layer hierarchy: ${rel.sourceLayer} \u2192 ${rel.targetLayer}`))) : issues.push(`Unknown predicate: ${rel.predicate}`), {
|
|
112
|
+
isValid: issues.length === 0,
|
|
113
|
+
category: rel.category,
|
|
114
|
+
predicate: rel.predicate,
|
|
115
|
+
issues,
|
|
116
|
+
warnings
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Validate a batch of relationships
|
|
121
|
+
*/
|
|
122
|
+
async validateBatch(relationships) {
|
|
123
|
+
const results = [];
|
|
124
|
+
for (const rel of relationships) {
|
|
125
|
+
const result = await this.validateSemantics(rel);
|
|
126
|
+
results.push(result);
|
|
127
|
+
}
|
|
128
|
+
return results;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Find relationships that violate semantic rules
|
|
132
|
+
*/
|
|
133
|
+
async findSemanticViolations(relationships) {
|
|
134
|
+
return (await this.validateBatch(relationships)).filter((v) => !v.isValid || v.issues.length > 0);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Analyze relationship patterns
|
|
138
|
+
*/
|
|
139
|
+
async analyzePatterns(relationships) {
|
|
140
|
+
const byPredicate = {};
|
|
141
|
+
for (const rel of relationships)
|
|
142
|
+
byPredicate[rel.predicate] || (byPredicate[rel.predicate] = []), byPredicate[rel.predicate].push(rel);
|
|
143
|
+
const patterns = [];
|
|
144
|
+
for (const [predicate, rels] of Object.entries(byPredicate)) {
|
|
145
|
+
const relationshipType = this.relationshipTypeMap.get(predicate), examples = rels.slice(0, 3).map((r) => `${r.source} \u2192 ${r.target}`), avgStrength = this.calculateAverageStrength(rels);
|
|
146
|
+
patterns.push({
|
|
147
|
+
predicate,
|
|
148
|
+
category: relationshipType?.category || "unknown",
|
|
149
|
+
count: rels.length,
|
|
150
|
+
percentage: rels.length / relationships.length * 100,
|
|
151
|
+
averageStrength: avgStrength,
|
|
152
|
+
examples
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return patterns.sort((a, b) => b.count - a.count);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Calculate average relationship strength
|
|
159
|
+
*/
|
|
160
|
+
calculateAverageStrength(relationships) {
|
|
161
|
+
if (relationships.length === 0)
|
|
162
|
+
return RelationshipStrength.Medium;
|
|
163
|
+
let strongCount = 0, weakCount = 0;
|
|
164
|
+
for (const rel of relationships)
|
|
165
|
+
rel.transitivity && rel.symmetry ? strongCount++ : rel.directionality === "unidirectional" && rel.reflexivity === !1 && weakCount++;
|
|
166
|
+
const strongPercentage = strongCount / relationships.length * 100, weakPercentage = weakCount / relationships.length * 100;
|
|
167
|
+
return strongPercentage > 50 ? RelationshipStrength.Strong : weakPercentage > 50 ? RelationshipStrength.Weak : RelationshipStrength.Medium;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get layer ordering for compliance checking
|
|
171
|
+
*/
|
|
172
|
+
getLayerOrder(layer1, layer2) {
|
|
173
|
+
const order1 = getLayerOrder(layer1), order2 = getLayerOrder(layer2);
|
|
174
|
+
return order1 - order2;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
RelationshipClassifier,
|
|
179
|
+
RelationshipStrength
|
|
180
|
+
};
|
|
181
|
+
//# sourceMappingURL=relationship-classifier.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/analysis/relationship-classifier.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Relationship Classifier - Semantic classification of relationships\n *\n * Classifies relationships by semantic category, strength, and directionality.\n * Analyzes relationship patterns, validates against schemas, and detects issues.\n */\n\nimport { RelationshipCatalog, RelationshipType } from \"../core/relationship-catalog.js\";\nimport { ClassifiedRelationship } from \"../core/report-data-model.js\";\nimport { getLayerOrder, isValidLayerName } from \"../core/layers.js\";\nimport type { Relationship } from \"../types/index.js\";\n\n/**\n * Relationship strength assessment\n */\nexport enum RelationshipStrength {\n Weak = \"weak\",\n Medium = \"medium\",\n Strong = \"strong\",\n}\n\n/**\n * Relationship pattern analysis result\n */\nexport interface RelationshipPattern {\n predicate: string;\n category: string;\n count: number;\n percentage: number;\n averageStrength: RelationshipStrength;\n examples: string[];\n}\n\n/**\n * Transitive analysis result\n */\nexport interface TransitiveAnalysis {\n predicate: string;\n isTransitive: boolean;\n chains: TransitiveChain[];\n}\n\n/**\n * Transitive chain (A -> B -> C where A is implied to relate to C)\n */\nexport interface TransitiveChain {\n elements: string[];\n pathLength: number;\n}\n\n/**\n * Classification statistics grouped by category\n */\nexport interface CategoryStatistics {\n category: string;\n count: number;\n percentage: number;\n predicates: string[];\n avgStrength: RelationshipStrength;\n}\n\n/**\n * Validates and analyzes semantic compliance\n */\nexport interface SemanticValidationResult {\n isValid: boolean;\n category: string;\n predicate: string;\n issues: string[];\n warnings: string[];\n}\n\n/**\n * Relationship Classifier\n */\nexport class RelationshipClassifier {\n private catalog: RelationshipCatalog;\n private relationshipTypeMap: Map<string, RelationshipType> = new Map();\n private catalogLoaded = false;\n\n constructor(catalog: RelationshipCatalog) {\n this.catalog = catalog;\n }\n\n /**\n * Load and prepare the catalog\n */\n async load(): Promise<void> {\n if (this.catalogLoaded) return;\n\n await this.catalog.load();\n const types = this.catalog.getAllTypes();\n\n for (const type of types) {\n this.relationshipTypeMap.set(type.predicate, type);\n }\n\n this.catalogLoaded = true;\n }\n\n /**\n * Classify a single relationship with detailed semantic information\n */\n async classify(\n rel: Relationship,\n relationshipId?: string\n ): Promise<ClassifiedRelationship> {\n await this.load();\n\n const sourceLayer = rel.source.split(\".\")[0];\n const targetLayer = rel.target.split(\".\")[0];\n const isCrossLayer = sourceLayer !== targetLayer;\n\n const relationshipType = this.relationshipTypeMap.get(rel.predicate);\n\n return {\n id: relationshipId || `${rel.source}\u2192${rel.predicate}\u2192${rel.target}`,\n source: rel.source,\n target: rel.target,\n predicate: rel.predicate,\n category: relationshipType?.category || \"unknown\",\n archimateAlignment: relationshipType?.archimateAlignment || null,\n directionality: relationshipType?.semantics?.directionality || \"unidirectional\",\n transitivity: relationshipType?.semantics?.transitivity || false,\n symmetry: relationshipType?.semantics?.symmetry || false,\n reflexivity: relationshipType?.semantics?.reflexivity,\n sourceLayer,\n targetLayer,\n isCrossLayer,\n isSpecCompliant: relationshipType !== undefined,\n };\n }\n\n /**\n * Classify a batch of relationships\n */\n async classifyBatch(\n relationships: Relationship[]\n ): Promise<ClassifiedRelationship[]> {\n const classified: ClassifiedRelationship[] = [];\n\n for (let i = 0; i < relationships.length; i++) {\n const rel = relationships[i];\n const relationshipId = `${rel.source}\u2192${rel.predicate}\u2192${rel.target}`;\n const classifiedRel = await this.classify(rel, relationshipId);\n classified.push(classifiedRel);\n }\n\n return classified;\n }\n\n /**\n * Get relationship breakdown by category\n */\n async getCategoryBreakdown(\n relationships: ClassifiedRelationship[]\n ): Promise<CategoryStatistics[]> {\n const byCategory: Record<string, ClassifiedRelationship[]> = {};\n\n for (const rel of relationships) {\n if (!byCategory[rel.category]) {\n byCategory[rel.category] = [];\n }\n byCategory[rel.category].push(rel);\n }\n\n const breakdown: CategoryStatistics[] = [];\n\n for (const [category, rels] of Object.entries(byCategory)) {\n const predicates = Array.from(new Set(rels.map((r) => r.predicate)));\n const avgStrength = this.calculateAverageStrength(rels);\n\n breakdown.push({\n category,\n count: rels.length,\n percentage: (rels.length / relationships.length) * 100,\n predicates,\n avgStrength,\n });\n }\n\n return breakdown.sort((a, b) => b.count - a.count);\n }\n\n /**\n * Analyze transitive relationships for a specific predicate\n */\n async analyzeTransitivity(\n relationships: ClassifiedRelationship[],\n predicate: string\n ): Promise<TransitiveAnalysis> {\n const type = this.relationshipTypeMap.get(predicate);\n const isTransitive = type?.semantics.transitivity || false;\n\n const chains: TransitiveChain[] = [];\n\n if (isTransitive) {\n // Build a map of relationships for this predicate\n const relsByPredicate = relationships.filter((r) => r.predicate === predicate);\n\n // Find chains A -> B -> C\n for (const rel1 of relsByPredicate) {\n for (const rel2 of relsByPredicate) {\n if (rel1.target === rel2.source && rel1.source !== rel2.target) {\n chains.push({\n elements: [rel1.source, rel1.target, rel2.target],\n pathLength: 2,\n });\n }\n }\n }\n\n // Remove duplicate chains\n const uniqueChains = Array.from(\n new Map(chains.map((c) => [c.elements.join(\"\u2192\"), c])).values()\n );\n\n return {\n predicate,\n isTransitive: true,\n chains: uniqueChains,\n };\n }\n\n return {\n predicate,\n isTransitive: false,\n chains: [],\n };\n }\n\n /**\n * Validate a relationship against semantic rules\n */\n async validateSemantics(\n rel: ClassifiedRelationship\n ): Promise<SemanticValidationResult> {\n await this.load();\n\n const issues: string[] = [];\n const warnings: string[] = [];\n\n const relationshipType = this.relationshipTypeMap.get(rel.predicate);\n\n if (!relationshipType) {\n issues.push(`Unknown predicate: ${rel.predicate}`);\n } else {\n // Check reflexivity\n if (!relationshipType.semantics.reflexivity && rel.source === rel.target) {\n issues.push(`Predicate \"${rel.predicate}\" does not support reflexive relationships`);\n }\n\n // Check symmetry\n if (relationshipType.semantics.symmetry && rel.directionality === \"unidirectional\") {\n warnings.push(`Predicate \"${rel.predicate}\" is symmetric but may be unidirectional`);\n }\n\n // Check layer direction for cross-layer relationships\n if (rel.isCrossLayer) {\n // First check if both layers are valid\n if (!isValidLayerName(rel.sourceLayer) || !isValidLayerName(rel.targetLayer)) {\n warnings.push(\n `Cross-layer relationship references unknown layer(s): ${rel.sourceLayer} \u2192 ${rel.targetLayer}`\n );\n } else {\n // Only check hierarchy if both layers are known\n const layerOrder = this.getLayerOrder(rel.sourceLayer, rel.targetLayer);\n if (layerOrder < 0) {\n warnings.push(\n `Cross-layer relationship violates layer hierarchy: ${rel.sourceLayer} \u2192 ${rel.targetLayer}`\n );\n }\n }\n }\n }\n\n return {\n isValid: issues.length === 0,\n category: rel.category,\n predicate: rel.predicate,\n issues,\n warnings,\n };\n }\n\n /**\n * Validate a batch of relationships\n */\n async validateBatch(\n relationships: ClassifiedRelationship[]\n ): Promise<SemanticValidationResult[]> {\n const results: SemanticValidationResult[] = [];\n\n for (const rel of relationships) {\n const result = await this.validateSemantics(rel);\n results.push(result);\n }\n\n return results;\n }\n\n /**\n * Find relationships that violate semantic rules\n */\n async findSemanticViolations(\n relationships: ClassifiedRelationship[]\n ): Promise<SemanticValidationResult[]> {\n const validations = await this.validateBatch(relationships);\n return validations.filter((v) => !v.isValid || v.issues.length > 0);\n }\n\n /**\n * Analyze relationship patterns\n */\n async analyzePatterns(\n relationships: ClassifiedRelationship[]\n ): Promise<RelationshipPattern[]> {\n const byPredicate: Record<string, ClassifiedRelationship[]> = {};\n\n for (const rel of relationships) {\n if (!byPredicate[rel.predicate]) {\n byPredicate[rel.predicate] = [];\n }\n byPredicate[rel.predicate].push(rel);\n }\n\n const patterns: RelationshipPattern[] = [];\n\n for (const [predicate, rels] of Object.entries(byPredicate)) {\n const relationshipType = this.relationshipTypeMap.get(predicate);\n const examples = rels.slice(0, 3).map((r) => `${r.source} \u2192 ${r.target}`);\n const avgStrength = this.calculateAverageStrength(rels);\n\n patterns.push({\n predicate,\n category: relationshipType?.category || \"unknown\",\n count: rels.length,\n percentage: (rels.length / relationships.length) * 100,\n averageStrength: avgStrength,\n examples,\n });\n }\n\n return patterns.sort((a, b) => b.count - a.count);\n }\n\n /**\n * Calculate average relationship strength\n */\n private calculateAverageStrength(\n relationships: ClassifiedRelationship[]\n ): RelationshipStrength {\n if (relationships.length === 0) return RelationshipStrength.Medium;\n\n let strongCount = 0;\n let weakCount = 0;\n\n for (const rel of relationships) {\n // Strong: transitive, symmetric relationships\n if (rel.transitivity && rel.symmetry) {\n strongCount++;\n }\n // Weak: unidirectional, non-reflexive\n else if (rel.directionality === \"unidirectional\" && rel.reflexivity === false) {\n weakCount++;\n }\n }\n\n const strongPercentage = (strongCount / relationships.length) * 100;\n const weakPercentage = (weakCount / relationships.length) * 100;\n\n if (strongPercentage > 50) {\n return RelationshipStrength.Strong;\n } else if (weakPercentage > 50) {\n return RelationshipStrength.Weak;\n }\n\n return RelationshipStrength.Medium;\n }\n\n /**\n * Get layer ordering for compliance checking\n */\n private getLayerOrder(layer1: string, layer2: string): number {\n const order1 = getLayerOrder(layer1);\n const order2 = getLayerOrder(layer2);\n return order1 - order2;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["RelationshipStrength"]
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=base-analyzer.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
function isEdgeType(value) {
|
|
3
|
+
return value === "CALLS" || value === "HTTP_CALLS" || value === "HANDLES";
|
|
4
|
+
}
|
|
5
|
+
function clampDepth(depth) {
|
|
6
|
+
return Math.max(Math.min(depth ?? 3, 10), 0);
|
|
7
|
+
}
|
|
8
|
+
function shapeCallGraphNode(responseNode, projectRoot) {
|
|
9
|
+
let sourceFile = responseNode.file_path || responseNode.source_file || "";
|
|
10
|
+
if (sourceFile && projectRoot)
|
|
11
|
+
try {
|
|
12
|
+
if (typeof sourceFile != "string" || typeof projectRoot != "string")
|
|
13
|
+
throw new TypeError(`Invalid path types: sourceFile=${typeof sourceFile}, projectRoot=${typeof projectRoot}`);
|
|
14
|
+
sourceFile = relative(projectRoot, sourceFile);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
17
|
+
console.warn(`Warning: Failed to compute relative path for "${sourceFile}": ${errorMessage}`);
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
qualified_name: responseNode.qualified_name || responseNode.id,
|
|
21
|
+
source_file: sourceFile,
|
|
22
|
+
source_symbol: responseNode.source_symbol || responseNode.id || "",
|
|
23
|
+
depth: typeof responseNode.depth == "number" ? responseNode.depth : 0,
|
|
24
|
+
edge_type: "CALLS"
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function determineEdgeType(nodeDepth, edges, targetNodeQualifiedName, validEdgeTypes = ["CALLS", "HTTP_CALLS", "HANDLES"]) {
|
|
28
|
+
const defaultEdgeType = validEdgeTypes[0] || "CALLS";
|
|
29
|
+
if (nodeDepth === 0)
|
|
30
|
+
return isEdgeType(defaultEdgeType) ? defaultEdgeType : "CALLS";
|
|
31
|
+
const incomingEdge = edges.find((edge) => edge.to_node === targetNodeQualifiedName);
|
|
32
|
+
return incomingEdge && incomingEdge.type && validEdgeTypes.includes(incomingEdge.type) && isEdgeType(incomingEdge.type) ? incomingEdge.type : isEdgeType(defaultEdgeType) ? defaultEdgeType : "CALLS";
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
clampDepth,
|
|
36
|
+
determineEdgeType,
|
|
37
|
+
shapeCallGraphNode
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=call-graph-utils.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/analyzers/call-graph-utils.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Utilities for call graph analysis\n */\n\nimport { relative } from \"node:path\";\nimport type { CallGraphNode } from \"./types.js\";\n\n/**\n * Valid edge types for call graph edges\n */\ntype EdgeType = \"CALLS\" | \"HTTP_CALLS\" | \"HANDLES\";\n\n/**\n * Type guard to ensure a value is a valid edge type\n */\nfunction isEdgeType(value: unknown): value is EdgeType {\n return value === \"CALLS\" || value === \"HTTP_CALLS\" || value === \"HANDLES\";\n}\n\n/**\n * Clamp depth to valid range (default 3, min 0, max 10)\n */\nexport function clampDepth(depth: number | undefined): number {\n return Math.max(Math.min(depth ?? 3, 10), 0);\n}\n\n/**\n * Shape raw response node to CallGraphNode\n */\nexport function shapeCallGraphNode(\n responseNode: any,\n projectRoot?: string\n): CallGraphNode {\n // Extract source file and compute relative path if projectRoot provided\n let sourceFile = responseNode.file_path || responseNode.source_file || \"\";\n if (sourceFile && projectRoot) {\n try {\n // Validate inputs are strings before calling path.relative()\n if (typeof sourceFile !== \"string\" || typeof projectRoot !== \"string\") {\n throw new TypeError(\n `Invalid path types: sourceFile=${typeof sourceFile}, projectRoot=${typeof projectRoot}`\n );\n }\n sourceFile = relative(projectRoot, sourceFile);\n } catch (error) {\n // Log the error but keep the original path\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.warn(\n `Warning: Failed to compute relative path for \"${sourceFile}\": ${errorMessage}`\n );\n }\n }\n\n return {\n qualified_name: responseNode.qualified_name || responseNode.id,\n source_file: sourceFile,\n source_symbol: responseNode.source_symbol || responseNode.id || \"\",\n depth: typeof responseNode.depth === \"number\" ? responseNode.depth : 0,\n edge_type: \"CALLS\",\n };\n}\n\n/**\n * Determine edge type based on node depth and edges list\n */\nexport function determineEdgeType(\n nodeDepth: number,\n edges: Array<{ from_node: string; to_node: string; type?: string }>,\n targetNodeQualifiedName: string,\n validEdgeTypes: string[] = [\"CALLS\", \"HTTP_CALLS\", \"HANDLES\"]\n): EdgeType {\n const defaultEdgeType = validEdgeTypes[0] || \"CALLS\";\n\n // For root nodes (depth 0), always use default\n if (nodeDepth === 0) {\n // Validate that default is a known edge type\n if (!isEdgeType(defaultEdgeType)) {\n return \"CALLS\"; // Fallback to safe default\n }\n return defaultEdgeType;\n }\n\n // For non-root nodes, find incoming edge\n const incomingEdge = edges.find(\n (edge) => edge.to_node === targetNodeQualifiedName\n );\n if (incomingEdge && incomingEdge.type && validEdgeTypes.includes(incomingEdge.type)) {\n // Validate that the edge type is known\n if (isEdgeType(incomingEdge.type)) {\n return incomingEdge.type;\n }\n }\n\n // Return validated default\n if (!isEdgeType(defaultEdgeType)) {\n return \"CALLS\"; // Fallback to safe default\n }\n return defaultEdgeType;\n}\n"],
|
|
5
|
+
"mappings": "AAIA,SAAS,gBAAgB;AAWzB,SAAS,WAAW,OAAc;AAChC,SAAO,UAAU,WAAW,UAAU,gBAAgB,UAAU;AAClE;AAKM,SAAU,WAAW,OAAyB;AAClD,SAAO,KAAK,IAAI,KAAK,IAAI,SAAS,GAAG,EAAE,GAAG,CAAC;AAC7C;AAKM,SAAU,mBACd,cACA,aAAoB;AAGpB,MAAI,aAAa,aAAa,aAAa,aAAa,eAAe;AACvE,MAAI,cAAc;AAChB,QAAI;AAEF,UAAI,OAAO,cAAe,YAAY,OAAO,eAAgB;AAC3D,cAAM,IAAI,UACR,kCAAkC,OAAO,UAAU,iBAAiB,OAAO,WAAW,EAAE;AAG5F,mBAAa,SAAS,aAAa,UAAU;IAC/C,SAAS,OAAO;AAEd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,cAAQ,KACN,iDAAiD,UAAU,MAAM,YAAY,EAAE;IAEnF;AAGF,SAAO;IACL,gBAAgB,aAAa,kBAAkB,aAAa;IAC5D,aAAa;IACb,eAAe,aAAa,iBAAiB,aAAa,MAAM;IAChE,OAAO,OAAO,aAAa,SAAU,WAAW,aAAa,QAAQ;IACrE,WAAW;;AAEf;AAKM,SAAU,kBACd,WACA,OACA,yBACA,iBAA2B,CAAC,SAAS,cAAc,SAAS,GAAC;AAE7D,QAAM,kBAAkB,eAAe,CAAC,KAAK;AAG7C,MAAI,cAAc;AAEhB,WAAK,WAAW,eAAe,IAGxB,kBAFE;AAMX,QAAM,eAAe,MAAM,KACzB,CAAC,SAAS,KAAK,YAAY,uBAAuB;AAEpD,SAAI,gBAAgB,aAAa,QAAQ,eAAe,SAAS,aAAa,IAAI,KAE5E,WAAW,aAAa,IAAI,IACvB,aAAa,OAKnB,WAAW,eAAe,IAGxB,kBAFE;AAGX;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|