@documentation-robotics/cli 0.1.0 → 0.1.5
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 +206 -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 +155 -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 +37 -13
- 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
|
@@ -4,13 +4,28 @@ import path from "path";
|
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { Model } from "../core/model.js";
|
|
6
6
|
import { Validator } from "../validators/validator.js";
|
|
7
|
+
import { ValidationFormatter } from "../validators/validation-formatter.js";
|
|
8
|
+
import { getErrorMessage } from "../utils/errors.js";
|
|
9
|
+
import { RELATIONSHIPS_BY_SOURCE, RELATIONSHIPS_BY_DESTINATION } from "../generated/relationship-index.js";
|
|
10
|
+
import { getActiveSpan } from "../telemetry/index.js";
|
|
11
|
+
async function findJsonFiles(dir, baseDir = dir) {
|
|
12
|
+
const entries = await fs.readdir(dir, { withFileTypes: !0 }), files = [];
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
const fullPath = path.join(dir, entry.name);
|
|
15
|
+
if (entry.isDirectory() && entry.name !== "layers") {
|
|
16
|
+
const subFiles = await findJsonFiles(fullPath, baseDir);
|
|
17
|
+
files.push(...subFiles);
|
|
18
|
+
} else entry.name.endsWith(".json") && entry.isFile() && files.push(path.relative(baseDir, fullPath));
|
|
19
|
+
}
|
|
20
|
+
return files;
|
|
21
|
+
}
|
|
7
22
|
async function validateSchemaSynchronization() {
|
|
8
23
|
console.log(""), console.log(ansis.bold("Validating schema synchronization...")), console.log("");
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url), __dirname = path.dirname(__filename), projectRoot = path.resolve(__dirname, "../../.."), specSchemaDir = path.join(projectRoot, "spec", "
|
|
10
|
-
if (
|
|
24
|
+
const __filename = fileURLToPath(import.meta.url), __dirname = path.dirname(__filename), projectRoot = path.resolve(__dirname, "../../.."), specSchemaDir = path.join(projectRoot, "spec", "dist"), bundledSchemaDir = path.join(__dirname, "../schemas/bundled"), specSchemaFiles = await findJsonFiles(specSchemaDir), bundledSchemaFiles = await findJsonFiles(bundledSchemaDir);
|
|
25
|
+
if (specSchemaFiles.length === 0)
|
|
11
26
|
throw new Error("No schema files found in spec/schemas/");
|
|
12
27
|
let mismatches = [];
|
|
13
|
-
for (const schemaFile of
|
|
28
|
+
for (const schemaFile of specSchemaFiles) {
|
|
14
29
|
const specPath = path.join(specSchemaDir, schemaFile), bundledPath = path.join(bundledSchemaDir, schemaFile);
|
|
15
30
|
try {
|
|
16
31
|
const specContent = await fs.readFile(specPath, "utf-8");
|
|
@@ -24,45 +39,149 @@ async function validateSchemaSynchronization() {
|
|
|
24
39
|
throw error;
|
|
25
40
|
}
|
|
26
41
|
} catch (error) {
|
|
27
|
-
const message =
|
|
42
|
+
const message = getErrorMessage(error);
|
|
28
43
|
mismatches.push(` ${ansis.red("\u2717")} ${schemaFile} - Error reading spec schema: ${message}`);
|
|
29
44
|
}
|
|
30
45
|
}
|
|
31
46
|
for (const bundledFile of bundledSchemaFiles)
|
|
32
|
-
|
|
47
|
+
specSchemaFiles.includes(bundledFile) || mismatches.push(` ${ansis.red("\u2717")} ${bundledFile} - Extra file in cli/src/schemas/bundled/ (not in spec/)`);
|
|
33
48
|
if (mismatches.length > 0) {
|
|
34
49
|
console.log(""), console.log(ansis.bold(ansis.red(`\u2717 Schema synchronization failed with ${mismatches.length} issue(s):`))), console.log("");
|
|
35
50
|
for (const mismatch of mismatches)
|
|
36
51
|
console.log(mismatch);
|
|
37
|
-
throw console.log(""), console.log(ansis.dim("To fix:
|
|
52
|
+
throw console.log(""), console.log(ansis.dim("To fix: Run 'npm run build:spec' at repo root, then 'npm run build' in cli/ to sync spec/dist/ \u2192 cli/src/schemas/bundled/")), console.log(""), new Error(`Schema synchronization failed with ${mismatches.length} issue(s)`);
|
|
38
53
|
} else
|
|
39
54
|
console.log(""), console.log(ansis.green("\u2713 All schemas synchronized")), console.log("");
|
|
40
55
|
}
|
|
56
|
+
async function validateOrphansOnly(model, outputPath) {
|
|
57
|
+
const stats = ValidationFormatter.calculateStats(model);
|
|
58
|
+
if (stats.orphanedElements.length === 0) {
|
|
59
|
+
outputPath ? (await fs.writeFile(outputPath, JSON.stringify({ total: 0, byLayer: {} }, null, 2), "utf-8"), console.log(`
|
|
60
|
+
Orphan report exported to ${outputPath}`)) : console.log(ansis.green(`
|
|
61
|
+
\u2713 No orphaned elements found. All elements are connected.`));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const typesInModel = /* @__PURE__ */ new Set();
|
|
65
|
+
for (const [, layer] of model.layers)
|
|
66
|
+
for (const element of layer.listElements()) {
|
|
67
|
+
const parts2 = (element.path || element.id).split(".");
|
|
68
|
+
parts2.length >= 2 && typesInModel.add(`${parts2[0]}.${parts2[1]}`);
|
|
69
|
+
}
|
|
70
|
+
const byLayer = /* @__PURE__ */ new Map();
|
|
71
|
+
for (const elementId of stats.orphanedElements.sort()) {
|
|
72
|
+
const parts2 = elementId.split("."), layer = parts2[0] ?? "unknown", specNodeType = parts2.length >= 2 ? `${parts2[0]}.${parts2[1]}` : elementId, outgoingRels = RELATIONSHIPS_BY_SOURCE.get(specNodeType) ?? [], allDestTypes = [...new Set(outgoingRels.map((r) => r.destinationSpecNodeId))], reachableDestTypes = allDestTypes.filter((t) => typesInModel.has(t)), reachablePredicates = [...new Set(outgoingRels.filter((r) => reachableDestTypes.includes(r.destinationSpecNodeId)).map((r) => r.predicate))], incomingRels = RELATIONSHIPS_BY_DESTINATION.get(specNodeType) ?? [], reachableIncomingSourceTypes = [...new Set(incomingRels.map((r) => r.sourceSpecNodeId))].filter((t) => typesInModel.has(t)), hasOutgoingTargets = reachableDestTypes.length > 0, hasIncomingSources = reachableIncomingSourceTypes.length > 0, hasAnySchemas = outgoingRels.length > 0 || incomingRels.length > 0;
|
|
73
|
+
let status;
|
|
74
|
+
hasAnySchemas ? !hasOutgoingTargets && !hasIncomingSources ? status = "dead-end" : status = "connectable" : status = "no-schema", byLayer.has(layer) || byLayer.set(layer, []), byLayer.get(layer).push({
|
|
75
|
+
id: elementId,
|
|
76
|
+
type: specNodeType,
|
|
77
|
+
status,
|
|
78
|
+
reachablePredicates,
|
|
79
|
+
reachableTargetTypes: reachableDestTypes,
|
|
80
|
+
needsTypes: allDestTypes
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (outputPath) {
|
|
84
|
+
const jsonOut = {
|
|
85
|
+
total: stats.orphanedElements.length,
|
|
86
|
+
byLayer: Object.fromEntries([...byLayer.entries()].map(([layer, items]) => [layer, items]))
|
|
87
|
+
};
|
|
88
|
+
await fs.writeFile(outputPath, JSON.stringify(jsonOut, null, 2), "utf-8"), console.log(`
|
|
89
|
+
Orphan report exported to ${outputPath}`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
console.log(ansis.bold(`
|
|
93
|
+
Orphaned Elements (${stats.orphanedElements.length})`)), console.log(ansis.dim(`Elements with no intra-layer relationships and no cross-layer references
|
|
94
|
+
`));
|
|
95
|
+
let deadEndCount = 0, connectableCount = 0;
|
|
96
|
+
for (const [layerName, items] of byLayer) {
|
|
97
|
+
console.log(ansis.bold(ansis.cyan(` ${layerName} (${items.length})`)));
|
|
98
|
+
for (const item of items)
|
|
99
|
+
if (item.status === "no-schema")
|
|
100
|
+
console.log(` ${ansis.dim("\u25CB")} ${item.id}`), console.log(` ${ansis.dim("No outgoing relationship schemas defined for type " + item.type)}`);
|
|
101
|
+
else if (item.status === "dead-end") {
|
|
102
|
+
deadEndCount++;
|
|
103
|
+
const needsPreview = item.needsTypes.slice(0, 4).join(", ") + (item.needsTypes.length > 4 ? ` +${item.needsTypes.length - 4} more` : "");
|
|
104
|
+
console.log(` ${ansis.red("\u2717")} ${item.id} ${ansis.dim("(dead-end)")}`), console.log(` ${ansis.dim("Needs: " + needsPreview)}`);
|
|
105
|
+
} else {
|
|
106
|
+
connectableCount++;
|
|
107
|
+
const predsPreview = item.reachablePredicates.slice(0, 3).join(", "), targetsPreview = item.reachableTargetTypes.slice(0, 3).join(", ");
|
|
108
|
+
console.log(` ${ansis.yellow("\u25CB")} ${item.id}`), console.log(` ${ansis.dim(`\u2192 try: ${predsPreview} \u2192 ${targetsPreview}`)}`);
|
|
109
|
+
}
|
|
110
|
+
console.log();
|
|
111
|
+
}
|
|
112
|
+
const noSchemaCount = stats.orphanedElements.length - connectableCount - deadEndCount, parts = [];
|
|
113
|
+
connectableCount > 0 && parts.push(`${connectableCount} connectable`), deadEndCount > 0 && parts.push(`${deadEndCount} dead-end (valid target types missing from model)`), noSchemaCount > 0 && parts.push(`${noSchemaCount} no-schema`), console.log(ansis.dim(`Summary: ${parts.length > 0 ? parts.join(", ") : "0 actionable"}`)), connectableCount > 0 && console.log(ansis.dim("Run /dr-relate --orphans to wire connectable elements"));
|
|
114
|
+
}
|
|
41
115
|
async function validateCommand(options) {
|
|
116
|
+
const activeSpan = getActiveSpan();
|
|
117
|
+
activeSpan && (activeSpan.setAttribute("validate.layers", options.layers?.join(",") || "all"), activeSpan.setAttribute("validate.strict", options.strict || !1), activeSpan.setAttribute("validate.verbose", options.verbose || !1), activeSpan.setAttribute("validate.orphans", options.orphans || !1), activeSpan.setAttribute("validate.schemas", options.schemas || options.schema || !1), activeSpan.setAttribute("validate.output", options.output || "console"));
|
|
42
118
|
try {
|
|
43
119
|
if (options.schemas || options.schema) {
|
|
44
|
-
await validateSchemaSynchronization();
|
|
120
|
+
await validateSchemaSynchronization(), activeSpan && (activeSpan.setAttribute("validate.mode", "schema-sync"), activeSpan.setAttribute("validate.result", "success"));
|
|
45
121
|
return;
|
|
46
122
|
}
|
|
47
|
-
const model = await Model.load(options.model
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
console.log(ansis.red(` [${error.layer}] ${error.message}`)), error.elementId && console.log(ansis.dim(` Element: ${error.elementId}`)), error.fixSuggestion && console.log(ansis.dim(` \u2192 Suggestion: ${error.fixSuggestion}`));
|
|
54
|
-
console.log("");
|
|
123
|
+
const model = await Model.load(options.model, options.layers ? { layers: options.layers } : {});
|
|
124
|
+
if (options.orphans) {
|
|
125
|
+
activeSpan && activeSpan.setAttribute("validate.mode", "orphans-only");
|
|
126
|
+
const activeChangesetId2 = model.getActiveChangesetId(), modelForOrphans = activeChangesetId2 ? await model.getVirtualProjectionEngine().projectModel(model, activeChangesetId2) : model;
|
|
127
|
+
await validateOrphansOnly(modelForOrphans, options.output), activeSpan && activeSpan.setAttribute("validate.result", "success");
|
|
128
|
+
return;
|
|
55
129
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
130
|
+
const validator = new Validator(), activeChangesetId = model.getActiveChangesetId(), modelToValidate = activeChangesetId ? await model.getVirtualProjectionEngine().projectModel(model, activeChangesetId) : model, result = await validator.validateModel(modelToValidate), stats = ValidationFormatter.calculateStats(modelToValidate);
|
|
131
|
+
for (const orphanId of stats.orphanedElements)
|
|
132
|
+
result.addWarning({
|
|
133
|
+
message: `Element '${orphanId}' is orphaned (no cross-layer references or intra-layer relationships)`,
|
|
134
|
+
layer: orphanId.split(".")[0] ?? "",
|
|
135
|
+
elementId: orphanId,
|
|
136
|
+
category: "orphan",
|
|
137
|
+
fixSuggestion: "Add cross-layer references or relationships to connect this element to the rest of the model"
|
|
138
|
+
});
|
|
139
|
+
for (const [layerName, layer] of modelToValidate.layers)
|
|
140
|
+
for (const element of layer.listElements()) {
|
|
141
|
+
const elementId = element.path || element.id;
|
|
142
|
+
element.source_reference || result.addWarning({
|
|
143
|
+
message: `Element '${elementId}' has no source reference`,
|
|
144
|
+
layer: layerName,
|
|
145
|
+
elementId,
|
|
146
|
+
fixSuggestion: "Add a source_reference with provenance to link this element to its implementation"
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (options.strict)
|
|
150
|
+
for (const [layerName, layer] of modelToValidate.layers)
|
|
151
|
+
for (const element of layer.listElements()) {
|
|
152
|
+
const elementId = element.path || element.id;
|
|
153
|
+
(!element.description || element.description.trim() === "") && result.addWarning({
|
|
154
|
+
message: `Element '${elementId}' has no description`,
|
|
155
|
+
layer: layerName,
|
|
156
|
+
elementId,
|
|
157
|
+
fixSuggestion: "Add a description to document what this element represents"
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (activeSpan && (activeSpan.setAttribute("validate.valid", result.isValid()), activeSpan.setAttribute("validate.error_count", result.errors.length), activeSpan.setAttribute("validate.warning_count", result.warnings.length), activeSpan.setAttribute("validate.orphan_count", stats.orphanedElements.length)), options.output) {
|
|
161
|
+
let content;
|
|
162
|
+
if (options.output.endsWith(".md") || options.output.endsWith(".markdown") ? content = ValidationFormatter.toMarkdown(result, modelToValidate) : options.output.endsWith(".json") ? content = JSON.stringify(ValidationFormatter.toJSON(result, modelToValidate), null, 2) : content = JSON.stringify(ValidationFormatter.toJSON(result, modelToValidate), null, 2), await fs.writeFile(options.output, content, "utf-8"), console.log(`
|
|
163
|
+
Validation report exported to ${options.output}`), !result.isValid())
|
|
164
|
+
throw new Error("Validation failed");
|
|
165
|
+
activeSpan && activeSpan.setAttribute("validate.result", "success");
|
|
166
|
+
return;
|
|
61
167
|
}
|
|
62
|
-
|
|
168
|
+
const formatted = ValidationFormatter.format(result, modelToValidate, {
|
|
169
|
+
verbose: options.verbose,
|
|
170
|
+
quiet: options.quiet
|
|
171
|
+
});
|
|
172
|
+
if (console.log(formatted), result.isValid()) {
|
|
173
|
+
if (options.strict && result.warnings.length > 0)
|
|
174
|
+
throw console.log(ansis.red("Strict mode enabled: treating warnings as errors")), new Error("Validation failed (strict mode)");
|
|
175
|
+
activeSpan && activeSpan.setAttribute("validate.result", "success");
|
|
176
|
+
return;
|
|
177
|
+
} else
|
|
178
|
+
throw new Error("Validation failed");
|
|
63
179
|
} catch (error) {
|
|
64
|
-
|
|
65
|
-
|
|
180
|
+
activeSpan?.setAttribute("validate.result", "error");
|
|
181
|
+
const message = getErrorMessage(error);
|
|
182
|
+
throw console.error(ansis.red(`Error: ${message}`)), error instanceof Error && error.stack && (console.error(ansis.dim(`
|
|
183
|
+
Full error details:`)), console.error(ansis.dim(error.stack))), process.env.DEBUG && (console.error(ansis.dim(`
|
|
184
|
+
Debug mode enabled. Additional context:`)), error instanceof Error && (console.error(ansis.dim(`Error name: ${error.name}`)), console.error(ansis.dim(`Error cause: ${error.cause || "none"}`)))), error;
|
|
66
185
|
}
|
|
67
186
|
}
|
|
68
187
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/validate.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Validate the architecture model\n */\n\nimport ansis from 'ansis';\nimport { promises as fs } from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { Model } from '../core/model.js';\nimport { Validator } from '../validators/validator.js';\n\nexport interface ValidateOptions {\n layers?: string[];\n strict?: boolean;\n verbose?: boolean;\n debug?: boolean;\n model?: string;\n // Python CLI compatibility options\n all?: boolean;\n markdown?: boolean;\n schemas?: boolean;\n schema?: boolean; // Alias for schemas\n relationships?: boolean;\n structure?: boolean;\n naming?: boolean;\n references?: boolean;\n}\n\n/**\n * Validate schema synchronization between spec/ and cli/src/schemas/bundled/\n * @throws {Error} if schema synchronization validation fails\n */\nasync function validateSchemaSynchronization(): Promise<void> {\n console.log('');\n console.log(ansis.bold('Validating schema synchronization...'));\n console.log('');\n\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n // Resolve paths relative to project root\n const projectRoot = path.resolve(__dirname, '../../..');\n const specSchemaDir = path.join(projectRoot, 'spec', 'schemas');\n const bundledSchemaDir = path.join(__dirname, '../schemas/bundled');\n\n const specSchemaFiles = await fs.readdir(specSchemaDir);\n const bundledSchemaFiles = await fs.readdir(bundledSchemaDir);\n\n const schemaFiles = specSchemaFiles.filter(f => f.endsWith('.json'));\n\n if (schemaFiles.length === 0) {\n throw new Error('No schema files found in spec/schemas/');\n }\n\n let mismatches: string[] = [];\n\n for (const schemaFile of schemaFiles) {\n const specPath = path.join(specSchemaDir, schemaFile);\n const bundledPath = path.join(bundledSchemaDir, schemaFile);\n\n try {\n const specContent = await fs.readFile(specPath, 'utf-8');\n\n try {\n const bundledContent = await fs.readFile(bundledPath, 'utf-8');\n\n // Normalize JSON to account for formatting differences\n const specParsed = JSON.parse(specContent);\n const bundledParsed = JSON.parse(bundledContent);\n const specNormalized = JSON.stringify(specParsed, null, 2);\n const bundledNormalized = JSON.stringify(bundledParsed, null, 2);\n\n if (specNormalized !== bundledNormalized) {\n mismatches.push(\n ` ${ansis.red('\u2717')} ${schemaFile} - Content differs between spec/ and cli/src/schemas/bundled/`\n );\n } else {\n console.log(` ${ansis.green('\u2713')} ${schemaFile}`);\n }\n } catch (error) {\n if ((error as any).code === 'ENOENT') {\n mismatches.push(\n ` ${ansis.red('\u2717')} ${schemaFile} - Missing in cli/src/schemas/bundled/`\n );\n } else {\n throw error;\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n mismatches.push(` ${ansis.red('\u2717')} ${schemaFile} - Error reading spec schema: ${message}`);\n }\n }\n\n // Check for extra files in bundled that aren't in spec\n for (const bundledFile of bundledSchemaFiles) {\n if (bundledFile.endsWith('.json') && !schemaFiles.includes(bundledFile)) {\n mismatches.push(\n ` ${ansis.red('\u2717')} ${bundledFile} - Extra file in cli/src/schemas/bundled/ (not in spec/)`\n );\n }\n }\n\n if (mismatches.length > 0) {\n console.log('');\n console.log(ansis.bold(ansis.red(`\u2717 Schema synchronization failed with ${mismatches.length} issue(s):`)));\n console.log('');\n for (const mismatch of mismatches) {\n console.log(mismatch);\n }\n console.log('');\n console.log(ansis.dim('To fix: Ensure spec/schemas/*.json matches cli/src/schemas/bundled/*.json'));\n console.log('');\n throw new Error(`Schema synchronization failed with ${mismatches.length} issue(s)`);\n } else {\n console.log('');\n console.log(ansis.green('\u2713 All schemas synchronized'));\n console.log('');\n }\n}\n\nexport async function validateCommand(options: ValidateOptions): Promise<void> {\n try {\n // Handle schema validation flag\n if (options.schemas || options.schema) {\n await validateSchemaSynchronization();\n return;\n }\n\n // Load model\n const model = await Model.load(options.model);\n\n // Validate\n const validator = new Validator();\n\n console.log('');\n console.log(ansis.bold('Validating model...'));\n console.log('');\n\n const result = await validator.validateModel(model);\n\n // Display errors\n if (result.errors.length > 0) {\n console.log(ansis.bold(ansis.red(`\u2717 ${result.errors.length} error(s):`)));\n console.log('');\n for (const error of result.errors) {\n console.log(ansis.red(` [${error.layer}] ${error.message}`));\n if (error.elementId) {\n console.log(ansis.dim(` Element: ${error.elementId}`));\n }\n if (error.fixSuggestion) {\n console.log(ansis.dim(` \u2192 Suggestion: ${error.fixSuggestion}`));\n }\n }\n console.log('');\n }\n\n // Display warnings\n if (result.warnings.length > 0) {\n console.log(ansis.bold(ansis.yellow(`\u26A0 ${result.warnings.length} warning(s):`)));\n console.log('');\n for (const warning of result.warnings) {\n console.log(ansis.yellow(` [${warning.layer}] ${warning.message}`));\n if (warning.elementId) {\n console.log(ansis.dim(` Element: ${warning.elementId}`));\n }\n if (warning.fixSuggestion) {\n console.log(ansis.dim(` \u2192 Suggestion: ${warning.fixSuggestion}`));\n }\n }\n console.log('');\n }\n\n // Display summary\n if (result.isValid()) {\n if (result.warnings.length === 0) {\n console.log(ansis.green('\u2713 Validation passed'));\n console.log('');\n process.exit(0);\n } else {\n console.log(\n ansis.yellow(\n `\u2713 Validation passed with ${result.warnings.length} warning(s)`\n )\n );\n console.log('');\n if (options.strict) {\n console.log(ansis.red('Strict mode enabled: treating warnings as errors'));\n process.exit(1);\n } else {\n process.exit(0);\n }\n }\n } else {\n console.log(\n ansis.red(`\u2717 Validation failed with ${result.errors.length} error(s)`)\n );\n console.log('');\n process.exit(1);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n if (process.env.DEBUG) {\n console.error((error as Error).stack);\n }\n process.exit(1);\n }\n}\n"],
|
|
5
|
-
"mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,YAAY,UAAU;AAC/B,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,aAAa;AACtB,SAAS,iBAAiB;
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["/**\n * Validate the architecture model\n */\n\nimport ansis from \"ansis\";\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { Model } from \"../core/model.js\";\nimport { Validator } from \"../validators/validator.js\";\nimport { ValidationFormatter } from \"../validators/validation-formatter.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { RELATIONSHIPS_BY_SOURCE, RELATIONSHIPS_BY_DESTINATION } from \"../generated/relationship-index.js\";\nimport { getActiveSpan } from \"../telemetry/index.js\";\n\n\nexport interface ValidateOptions {\n layers?: string[];\n strict?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n output?: string;\n debug?: boolean;\n model?: string;\n orphans?: boolean;\n // Python CLI compatibility options\n all?: boolean;\n markdown?: boolean;\n schemas?: boolean;\n schema?: boolean; // Alias for schemas\n relationships?: boolean;\n structure?: boolean;\n naming?: boolean;\n references?: boolean;\n}\n\n/**\n * Validate schema synchronization between spec/ and cli/src/schemas/bundled/\n * @throws {Error} if schema synchronization validation fails\n */\n/**\n * Recursively find all JSON schema files in a directory\n * Excludes 'layers' subdirectory since layer instances are not schemas\n */\nasync function findJsonFiles(dir: string, baseDir: string = dir): Promise<string[]> {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n // Skip 'layers' directory - layer instances are synced but are not schemas\n if (entry.isDirectory() && entry.name !== \"layers\") {\n const subFiles = await findJsonFiles(fullPath, baseDir);\n files.push(...subFiles);\n } else if (entry.name.endsWith(\".json\") && entry.isFile()) {\n // Store relative path from base directory\n files.push(path.relative(baseDir, fullPath));\n }\n }\n\n return files;\n}\n\nasync function validateSchemaSynchronization(): Promise<void> {\n console.log(\"\");\n console.log(ansis.bold(\"Validating schema synchronization...\"));\n console.log(\"\");\n\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n // Resolve paths relative to project root\n const projectRoot = path.resolve(__dirname, \"../../..\");\n // Compare spec/dist/ (14 compiled flat files) vs dist/schemas/bundled/ (same 14 files)\n // spec/schemas/ contains individual source files; spec/dist/ is the compiled distribution\n const specSchemaDir = path.join(projectRoot, \"spec\", \"dist\");\n const bundledSchemaDir = path.join(__dirname, \"../schemas/bundled\");\n\n // Find all JSON files recursively\n const specSchemaFiles = await findJsonFiles(specSchemaDir);\n const bundledSchemaFiles = await findJsonFiles(bundledSchemaDir);\n\n if (specSchemaFiles.length === 0) {\n throw new Error(\"No schema files found in spec/schemas/\");\n }\n\n let mismatches: string[] = [];\n\n for (const schemaFile of specSchemaFiles) {\n const specPath = path.join(specSchemaDir, schemaFile);\n const bundledPath = path.join(bundledSchemaDir, schemaFile);\n\n try {\n const specContent = await fs.readFile(specPath, \"utf-8\");\n\n try {\n const bundledContent = await fs.readFile(bundledPath, \"utf-8\");\n\n // Normalize JSON to account for formatting differences\n const specParsed = JSON.parse(specContent);\n const bundledParsed = JSON.parse(bundledContent);\n const specNormalized = JSON.stringify(specParsed, null, 2);\n const bundledNormalized = JSON.stringify(bundledParsed, null, 2);\n\n if (specNormalized !== bundledNormalized) {\n mismatches.push(\n ` ${ansis.red(\"\u2717\")} ${schemaFile} - Content differs between spec/ and cli/src/schemas/bundled/`\n );\n } else {\n console.log(` ${ansis.green(\"\u2713\")} ${schemaFile}`);\n }\n } catch (error) {\n if ((error as any).code === \"ENOENT\") {\n mismatches.push(\n ` ${ansis.red(\"\u2717\")} ${schemaFile} - Missing in cli/src/schemas/bundled/`\n );\n } else {\n throw error;\n }\n }\n } catch (error) {\n const message = getErrorMessage(error);\n mismatches.push(` ${ansis.red(\"\u2717\")} ${schemaFile} - Error reading spec schema: ${message}`);\n }\n }\n\n // Check for extra files in bundled that aren't in spec\n for (const bundledFile of bundledSchemaFiles) {\n if (!specSchemaFiles.includes(bundledFile)) {\n mismatches.push(\n ` ${ansis.red(\"\u2717\")} ${bundledFile} - Extra file in cli/src/schemas/bundled/ (not in spec/)`\n );\n }\n }\n\n if (mismatches.length > 0) {\n console.log(\"\");\n console.log(\n ansis.bold(ansis.red(`\u2717 Schema synchronization failed with ${mismatches.length} issue(s):`))\n );\n console.log(\"\");\n for (const mismatch of mismatches) {\n console.log(mismatch);\n }\n console.log(\"\");\n console.log(\n ansis.dim(\"To fix: Run 'npm run build:spec' at repo root, then 'npm run build' in cli/ to sync spec/dist/ \u2192 cli/src/schemas/bundled/\")\n );\n console.log(\"\");\n throw new Error(`Schema synchronization failed with ${mismatches.length} issue(s)`);\n } else {\n console.log(\"\");\n console.log(ansis.green(\"\u2713 All schemas synchronized\"));\n console.log(\"\");\n }\n}\n\n/**\n * Display structured orphan report grouped by layer, with dead-end detection.\n * For each orphan, checks whether valid relationship targets exist in the model.\n */\nasync function validateOrphansOnly(model: Model, outputPath?: string): Promise<void> {\n const stats = ValidationFormatter.calculateStats(model);\n\n if (stats.orphanedElements.length === 0) {\n const msg = \"No orphaned elements found. All elements are connected.\";\n if (outputPath) {\n await fs.writeFile(outputPath, JSON.stringify({ total: 0, byLayer: {} }, null, 2), \"utf-8\");\n console.log(`\\nOrphan report exported to ${outputPath}`);\n } else {\n console.log(ansis.green(`\\n\u2713 ${msg}`));\n }\n return;\n }\n\n // Build set of element types currently present in the model\n const typesInModel = new Set<string>();\n for (const [, layer] of model.layers) {\n for (const element of layer.listElements()) {\n const id = element.path || element.id;\n const parts = id.split(\".\");\n if (parts.length >= 2) typesInModel.add(`${parts[0]}.${parts[1]}`);\n }\n }\n\n // Group orphans by layer, annotated with dead-end status\n const byLayer = new Map<string, Array<{\n id: string;\n type: string;\n status: \"dead-end\" | \"connectable\" | \"no-schema\";\n reachablePredicates: string[];\n reachableTargetTypes: string[];\n needsTypes: string[];\n }>>();\n\n for (const elementId of stats.orphanedElements.sort()) {\n const parts = elementId.split(\".\");\n const layer = parts[0] ?? \"unknown\";\n const specNodeType = parts.length >= 2 ? `${parts[0]}.${parts[1]}` : elementId;\n\n // Outgoing: this element can point to others\n const outgoingRels = RELATIONSHIPS_BY_SOURCE.get(specNodeType) ?? [];\n const allDestTypes = [...new Set(outgoingRels.map(r => r.destinationSpecNodeId))];\n const reachableDestTypes = allDestTypes.filter(t => typesInModel.has(t));\n const reachablePredicates = [...new Set(\n outgoingRels.filter(r => reachableDestTypes.includes(r.destinationSpecNodeId)).map(r => r.predicate)\n )];\n\n // Incoming: other element types in the model can point to this element\n const incomingRels = RELATIONSHIPS_BY_DESTINATION.get(specNodeType) ?? [];\n const reachableIncomingSourceTypes = [...new Set(incomingRels.map(r => r.sourceSpecNodeId))]\n .filter(t => typesInModel.has(t));\n\n const hasOutgoingTargets = reachableDestTypes.length > 0;\n const hasIncomingSources = reachableIncomingSourceTypes.length > 0;\n const hasAnySchemas = outgoingRels.length > 0 || incomingRels.length > 0;\n\n let status: \"dead-end\" | \"connectable\" | \"no-schema\";\n if (!hasAnySchemas) {\n status = \"no-schema\";\n } else if (!hasOutgoingTargets && !hasIncomingSources) {\n status = \"dead-end\";\n } else {\n status = \"connectable\";\n }\n\n if (!byLayer.has(layer)) byLayer.set(layer, []);\n byLayer.get(layer)!.push({\n id: elementId,\n type: specNodeType,\n status,\n reachablePredicates,\n reachableTargetTypes: reachableDestTypes,\n needsTypes: allDestTypes,\n });\n }\n\n if (outputPath) {\n const jsonOut: Record<string, unknown> = {\n total: stats.orphanedElements.length,\n byLayer: Object.fromEntries(\n [...byLayer.entries()].map(([layer, items]) => [layer, items])\n ),\n };\n await fs.writeFile(outputPath, JSON.stringify(jsonOut, null, 2), \"utf-8\");\n console.log(`\\nOrphan report exported to ${outputPath}`);\n return;\n }\n\n console.log(ansis.bold(`\\nOrphaned Elements (${stats.orphanedElements.length})`));\n console.log(ansis.dim(\"Elements with no intra-layer relationships and no cross-layer references\\n\"));\n\n let deadEndCount = 0;\n let connectableCount = 0;\n\n for (const [layerName, items] of byLayer) {\n console.log(ansis.bold(ansis.cyan(` ${layerName} (${items.length})`)));\n for (const item of items) {\n if (item.status === \"no-schema\") {\n console.log(` ${ansis.dim(\"\u25CB\")} ${item.id}`);\n console.log(` ${ansis.dim(\"No outgoing relationship schemas defined for type \" + item.type)}`);\n } else if (item.status === \"dead-end\") {\n deadEndCount++;\n const needsPreview = item.needsTypes.slice(0, 4).join(\", \") +\n (item.needsTypes.length > 4 ? ` +${item.needsTypes.length - 4} more` : \"\");\n console.log(` ${ansis.red(\"\u2717\")} ${item.id} ${ansis.dim(\"(dead-end)\")}`);\n console.log(` ${ansis.dim(\"Needs: \" + needsPreview)}`);\n } else {\n connectableCount++;\n const predsPreview = item.reachablePredicates.slice(0, 3).join(\", \");\n const targetsPreview = item.reachableTargetTypes.slice(0, 3).join(\", \");\n console.log(` ${ansis.yellow(\"\u25CB\")} ${item.id}`);\n console.log(` ${ansis.dim(`\u2192 try: ${predsPreview} \u2192 ${targetsPreview}`)}`);\n }\n }\n console.log();\n }\n\n // Summary line\n const noSchemaCount = stats.orphanedElements.length - connectableCount - deadEndCount;\n const parts: string[] = [];\n if (connectableCount > 0) parts.push(`${connectableCount} connectable`);\n if (deadEndCount > 0) parts.push(`${deadEndCount} dead-end (valid target types missing from model)`);\n if (noSchemaCount > 0) parts.push(`${noSchemaCount} no-schema`);\n console.log(ansis.dim(`Summary: ${parts.length > 0 ? parts.join(\", \") : \"0 actionable\"}`));\n if (connectableCount > 0) {\n console.log(ansis.dim(\"Run /dr-relate --orphans to wire connectable elements\"));\n }\n}\n\nexport async function validateCommand(options: ValidateOptions): Promise<void> {\n // Annotate the root cli.execute span with validate-specific attributes\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.layers\", options.layers?.join(\",\") || \"all\");\n activeSpan.setAttribute(\"validate.strict\", options.strict || false);\n activeSpan.setAttribute(\"validate.verbose\", options.verbose || false);\n activeSpan.setAttribute(\"validate.orphans\", options.orphans || false);\n activeSpan.setAttribute(\"validate.schemas\", options.schemas || options.schema || false);\n activeSpan.setAttribute(\"validate.output\", options.output || \"console\");\n }\n\n try {\n // Handle schema validation flag\n if (options.schemas || options.schema) {\n await validateSchemaSynchronization();\n\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.mode\", \"schema-sync\");\n activeSpan.setAttribute(\"validate.result\", \"success\");\n }\n return;\n }\n\n // Load model (forward --layers filter so only requested layers are read from disk)\n const model = await Model.load(options.model, options.layers ? { layers: options.layers } : {});\n\n // --orphans mode: focused orphan report, skip full validation\n if (options.orphans) {\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.mode\", \"orphans-only\");\n }\n\n const activeChangesetId = model.getActiveChangesetId();\n const modelForOrphans = activeChangesetId\n ? (await model.getVirtualProjectionEngine().projectModel(model, activeChangesetId)) as unknown as typeof model\n : model;\n await validateOrphansOnly(modelForOrphans, options.output);\n\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.result\", \"success\");\n }\n return;\n }\n\n // Validate\n const validator = new Validator();\n\n // If an active changeset exists, project staged elements into the model so validators see them\n const activeChangesetId = model.getActiveChangesetId();\n const modelToValidate = activeChangesetId\n ? (await model.getVirtualProjectionEngine().projectModel(model, activeChangesetId)) as unknown as typeof model\n : model;\n\n const result = await validator.validateModel(modelToValidate);\n\n // Detect orphaned elements and add them as warnings so they appear in\n // the warning count and are surfaced consistently across all output formats.\n const stats = ValidationFormatter.calculateStats(modelToValidate);\n for (const orphanId of stats.orphanedElements) {\n result.addWarning({\n message: `Element '${orphanId}' is orphaned (no cross-layer references or intra-layer relationships)`,\n layer: orphanId.split(\".\")[0] ?? \"\",\n elementId: orphanId,\n category: \"orphan\",\n fixSuggestion: \"Add cross-layer references or relationships to connect this element to the rest of the model\",\n });\n }\n\n // Check source traceability in normal mode: elements without source_reference lack the\n // provenance link that dr-sync uses for drift detection. Surface this in every validate\n // run so users discover gaps without having to remember --strict.\n for (const [layerName, layer] of modelToValidate.layers) {\n for (const element of layer.listElements()) {\n const elementId = element.path || element.id;\n if (!element.source_reference) {\n result.addWarning({\n message: `Element '${elementId}' has no source reference`,\n layer: layerName,\n elementId,\n fixSuggestion:\n \"Add a source_reference with provenance to link this element to its implementation\",\n });\n }\n }\n }\n\n // Strict-mode additional checks: flag elements missing a description.\n if (options.strict) {\n for (const [layerName, layer] of modelToValidate.layers) {\n for (const element of layer.listElements()) {\n const elementId = element.path || element.id;\n\n if (!element.description || element.description.trim() === \"\") {\n result.addWarning({\n message: `Element '${elementId}' has no description`,\n layer: layerName,\n elementId,\n fixSuggestion: \"Add a description to document what this element represents\",\n });\n }\n }\n }\n }\n\n // Record validation results in span\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.valid\", result.isValid());\n activeSpan.setAttribute(\"validate.error_count\", result.errors.length);\n activeSpan.setAttribute(\"validate.warning_count\", result.warnings.length);\n activeSpan.setAttribute(\"validate.orphan_count\", stats.orphanedElements.length);\n }\n\n // Format and display output\n if (options.output) {\n // Export to file\n let content: string;\n\n if (options.output.endsWith(\".md\") || options.output.endsWith(\".markdown\")) {\n content = ValidationFormatter.toMarkdown(result, modelToValidate);\n } else if (options.output.endsWith(\".json\")) {\n content = JSON.stringify(ValidationFormatter.toJSON(result, modelToValidate), null, 2);\n } else {\n // Default to JSON\n content = JSON.stringify(ValidationFormatter.toJSON(result, modelToValidate), null, 2);\n }\n\n await fs.writeFile(options.output, content, \"utf-8\");\n console.log(`\\nValidation report exported to ${options.output}`);\n\n if (!result.isValid()) {\n throw new Error(\"Validation failed\");\n }\n\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.result\", \"success\");\n }\n return;\n }\n\n // Display formatted output\n const formatted = ValidationFormatter.format(result, modelToValidate, {\n verbose: options.verbose,\n quiet: options.quiet,\n });\n\n console.log(formatted);\n\n // Exit with appropriate code\n if (result.isValid()) {\n if (options.strict && result.warnings.length > 0) {\n console.log(ansis.red(\"Strict mode enabled: treating warnings as errors\"));\n throw new Error(\"Validation failed (strict mode)\");\n }\n\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.result\", \"success\");\n }\n return;\n } else {\n throw new Error(\"Validation failed\");\n }\n } catch (error) {\n activeSpan?.setAttribute(\"validate.result\", \"error\");\n\n const message = getErrorMessage(error);\n console.error(ansis.red(`Error: ${message}`));\n\n // Always preserve full error details in stderr for debugging\n if (error instanceof Error && error.stack) {\n console.error(ansis.dim(\"\\nFull error details:\"));\n console.error(ansis.dim(error.stack));\n }\n\n // Additional context for debugging\n if (process.env.DEBUG) {\n console.error(ansis.dim(\"\\nDebug mode enabled. Additional context:\"));\n if (error instanceof Error) {\n console.error(ansis.dim(`Error name: ${error.name}`));\n console.error(ansis.dim(`Error cause: ${(error as any).cause || \"none\"}`));\n }\n }\n\n // Re-throw to let root span handle exit\n throw error;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["parts", "activeChangesetId"]
|
|
7
7
|
}
|
package/dist/commands/version.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import ansis from "ansis";
|
|
2
|
-
import { readJSON, fileExists } from "../utils/file-io.js";
|
|
3
2
|
import { getCliBundledSpecVersion } from "../utils/spec-version.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
try {
|
|
8
|
-
return (await readJSON(packagePath)).version;
|
|
9
|
-
} catch {
|
|
10
|
-
}
|
|
11
|
-
return "0.1.0";
|
|
12
|
-
}
|
|
3
|
+
import { isTelemetryBuiltIn, isTelemetryConfigured } from "../telemetry/detect.js";
|
|
4
|
+
import { getSpecReferencePath, getModelPath } from "../utils/project-paths.js";
|
|
5
|
+
const gitHash = "d3cc2b3", cliVersion = "0.1.5";
|
|
13
6
|
async function versionCommand() {
|
|
14
|
-
const
|
|
15
|
-
|
|
7
|
+
const specVersion = getCliBundledSpecVersion(), telemetryBuiltIn = isTelemetryBuiltIn(), telemetryConfigured = await isTelemetryConfigured();
|
|
8
|
+
let telemetryStatus;
|
|
9
|
+
telemetryBuiltIn ? telemetryConfigured ? telemetryStatus = ansis.green("enabled, configured") : telemetryStatus = ansis.yellow("enabled, not configured") : telemetryStatus = ansis.dim("not available (build)"), console.log(ansis.bold("Documentation Robotics CLI")), console.log(`CLI Version: ${ansis.cyan(cliVersion)}`), console.log(`Spec Version: ${ansis.cyan(specVersion)}`), console.log(`Git Hash: ${ansis.cyan(gitHash)}`), console.log(`Telemetry: ${telemetryStatus}`), console.log(`Spec source: ${ansis.cyan("bundled with CLI")}`);
|
|
10
|
+
const drFolder = await getSpecReferencePath();
|
|
11
|
+
console.log(`DR folder: ${ansis.cyan(drFolder || "Not found")}`), console.log(`Model path: ${ansis.cyan(await getModelPath() || "Not found")}`);
|
|
16
12
|
}
|
|
17
13
|
export {
|
|
18
14
|
versionCommand
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/version.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Version Command - Display CLI and bundled spec versions\n */\n\nimport ansis from
|
|
5
|
-
"mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,
|
|
4
|
+
"sourcesContent": ["/**\n * Version Command - Display CLI and bundled spec versions\n */\n\nimport ansis from \"ansis\";\nimport { getCliBundledSpecVersion } from \"../utils/spec-version.js\";\nimport { isTelemetryBuiltIn, isTelemetryConfigured } from \"../telemetry/detect.js\";\nimport { getSpecReferencePath, getModelPath } from \"../utils/project-paths.js\";\n\n// Declare build-time constants (substituted by esbuild)\ndeclare const GIT_HASH: string;\ndeclare const CLI_VERSION: string;\n\nconst gitHash = typeof GIT_HASH !== \"undefined\" ? GIT_HASH : \"unknown\";\nconst cliVersion = typeof CLI_VERSION !== \"undefined\" ? CLI_VERSION : \"0.1.3\";\n\nexport async function versionCommand(): Promise<void> {\n const specVersion = getCliBundledSpecVersion();\n const telemetryBuiltIn = isTelemetryBuiltIn();\n const telemetryConfigured = await isTelemetryConfigured();\n\n // Determine telemetry status message\n let telemetryStatus: string;\n if (!telemetryBuiltIn) {\n telemetryStatus = ansis.dim(\"not available (build)\");\n } else if (telemetryConfigured) {\n telemetryStatus = ansis.green(\"enabled, configured\");\n } else {\n telemetryStatus = ansis.yellow(\"enabled, not configured\");\n }\n\n console.log(ansis.bold(\"Documentation Robotics CLI\"));\n console.log(`CLI Version: ${ansis.cyan(cliVersion)}`);\n console.log(`Spec Version: ${ansis.cyan(specVersion)}`);\n console.log(`Git Hash: ${ansis.cyan(gitHash)}`);\n console.log(`Telemetry: ${telemetryStatus}`);\n console.log(`Spec source: ${ansis.cyan(\"bundled with CLI\")}`);\n const drFolder = await getSpecReferencePath();\n console.log(`DR folder: ${ansis.cyan(drFolder || \"Not found\")}`);\n console.log(`Model path: ${ansis.cyan((await getModelPath()) || \"Not found\")}`);\n}\n"],
|
|
5
|
+
"mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,gCAAgC;AACzC,SAAS,oBAAoB,6BAA6B;AAC1D,SAAS,sBAAsB,oBAAoB;AAMnD,MAAM,UAA4C,WAC5C,aAAkD;AAExD,eAAsB,iBAAc;AAClC,QAAM,cAAc,yBAAwB,GACtC,mBAAmB,mBAAkB,GACrC,sBAAsB,MAAM,sBAAqB;AAGvD,MAAI;AACJ,EAAK,mBAEM,sBACT,kBAAkB,MAAM,MAAM,qBAAqB,IAEnD,kBAAkB,MAAM,OAAO,yBAAyB,IAJxD,kBAAkB,MAAM,IAAI,uBAAuB,GAOrD,QAAQ,IAAI,MAAM,KAAK,4BAA4B,CAAC,GACpD,QAAQ,IAAI,iBAAiB,MAAM,KAAK,UAAU,CAAC,EAAE,GACrD,QAAQ,IAAI,iBAAiB,MAAM,KAAK,WAAW,CAAC,EAAE,GACtD,QAAQ,IAAI,iBAAiB,MAAM,KAAK,OAAO,CAAC,EAAE,GAClD,QAAQ,IAAI,iBAAiB,eAAe,EAAE,GAC9C,QAAQ,IAAI,iBAAiB,MAAM,KAAK,kBAAkB,CAAC,EAAE;AAC7D,QAAM,WAAW,MAAM,qBAAoB;AAC3C,UAAQ,IAAI,iBAAiB,MAAM,KAAK,YAAY,WAAW,CAAC,EAAE,GAClE,QAAQ,IAAI,iBAAiB,MAAM,KAAM,MAAM,aAAY,KAAO,WAAW,CAAC,EAAE;AAClF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import ansis from "ansis";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { dirname } from "node:path";
|
|
2
5
|
import { Model } from "../core/model.js";
|
|
3
|
-
import { VisualizationServer } from "../server/server.js";
|
|
4
6
|
import { logVerbose, logDebug } from "../utils/globals.js";
|
|
7
|
+
import { CLIError } from "../utils/errors.js";
|
|
8
|
+
import { getSpecReferencePath, getModelPath } from "../utils/project-paths.js";
|
|
9
|
+
import { getErrorMessage } from "../utils/errors.js";
|
|
10
|
+
const isTelemetryEnabled = !1;
|
|
11
|
+
async function findAvailablePort(startPort) {
|
|
12
|
+
const { createServer } = await import("net");
|
|
13
|
+
for (let port = startPort; port <= 65535; port++)
|
|
14
|
+
if (await new Promise((resolve) => {
|
|
15
|
+
const server = createServer();
|
|
16
|
+
server.once("error", () => resolve(!1)), server.once("listening", () => {
|
|
17
|
+
server.close(), resolve(!0);
|
|
18
|
+
}), server.listen(port, "127.0.0.1");
|
|
19
|
+
}))
|
|
20
|
+
return port;
|
|
21
|
+
throw new Error("No available ports found");
|
|
22
|
+
}
|
|
5
23
|
async function visualizeCommand(options) {
|
|
6
24
|
try {
|
|
7
|
-
logDebug("Loading model for
|
|
8
|
-
const model = await Model.load(process.cwd(), { lazyLoad: !
|
|
9
|
-
logVerbose(`Model
|
|
25
|
+
logDebug("Loading model for validation...");
|
|
26
|
+
const model = await Model.load(process.cwd(), { lazyLoad: !0 });
|
|
27
|
+
logVerbose(`Model validated: ${model.manifest.name}`);
|
|
10
28
|
let port = 8080;
|
|
11
29
|
if (options.port) {
|
|
12
30
|
const portNum = parseInt(String(options.port), 10);
|
|
@@ -14,31 +32,143 @@ async function visualizeCommand(options) {
|
|
|
14
32
|
throw new Error(`Invalid port number: ${options.port}. Port must be between 1 and 65535.`);
|
|
15
33
|
port = portNum;
|
|
16
34
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
port = await findAvailablePort(port), port !== (options.port ? parseInt(String(options.port), 10) : 8080) && console.log(ansis.yellow(` Port ${options.port ?? 8080} is in use, using port ${port} instead`));
|
|
36
|
+
const authEnabled = !options.noAuth, authToken = options.token, withDanger = options.withDanger || !1;
|
|
37
|
+
logDebug(`Starting visualization server on port ${port}`), logDebug(`Authentication: ${authEnabled ? "enabled" : "disabled"}`), authEnabled && authToken ? logDebug("Using provided token for authentication") : authEnabled && logDebug("Token will be auto-generated"), withDanger && logDebug("Danger mode enabled - chat permissions will be skipped");
|
|
38
|
+
const commandDir = dirname(fileURLToPath(import.meta.url)), serverEntryPath = `${dirname(commandDir)}/server-entry.js`;
|
|
39
|
+
logDebug(`Server entry path: ${serverEntryPath}`);
|
|
40
|
+
let serverStartupSpan = null;
|
|
41
|
+
if (isTelemetryEnabled) {
|
|
42
|
+
logDebug("[Telemetry] Creating visualize.server.startup span");
|
|
43
|
+
const { startSpan } = await import("../telemetry/index.js");
|
|
44
|
+
serverStartupSpan = startSpan("visualize.server.startup", {
|
|
45
|
+
"server.port": port,
|
|
46
|
+
"server.auth_enabled": authEnabled,
|
|
47
|
+
"server.with_danger": withDanger
|
|
48
|
+
}), logDebug(`[Telemetry] Span created: ${serverStartupSpan ? "success" : "failed"}`);
|
|
21
49
|
} else
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
50
|
+
logDebug("[Telemetry] TELEMETRY_ENABLED is false - no spans will be created");
|
|
51
|
+
const env = {
|
|
52
|
+
...process.env,
|
|
53
|
+
DR_VISUALIZE_PORT: String(port),
|
|
54
|
+
DR_PROJECT_PATH: process.cwd(),
|
|
55
|
+
DR_AUTH_ENABLED: String(authEnabled),
|
|
56
|
+
DR_WITH_DANGER: String(withDanger)
|
|
57
|
+
}, { isDebug: getDebugState, isVerbose } = await import("../utils/globals.js");
|
|
58
|
+
getDebugState() && (env.DEBUG = "1", env.DR_TELEMETRY_DEBUG = "1", logDebug("Passing DEBUG=1 and DR_TELEMETRY_DEBUG=1 to subprocess")), isVerbose() && (env.VERBOSE = "1", logDebug("Passing VERBOSE=1 to subprocess")), authToken && (env.DR_AUTH_TOKEN = authToken), options.viewerPath && (env.DR_VIEWER_PATH = options.viewerPath, logDebug(`Using custom viewer from: ${options.viewerPath}`));
|
|
59
|
+
const serverProcess = spawn("bun", ["run", serverEntryPath], {
|
|
60
|
+
cwd: process.cwd(),
|
|
61
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
62
|
+
env
|
|
63
|
+
});
|
|
64
|
+
let authTokenFromServer = "", serverOutput = "", serverStartupShown = !1;
|
|
65
|
+
serverProcess.stdout && serverProcess.stdout.on("data", async (data) => {
|
|
66
|
+
const chunk = data.toString();
|
|
67
|
+
serverOutput += chunk;
|
|
68
|
+
const lines = chunk.split(`
|
|
69
|
+
`);
|
|
70
|
+
for (const rawLine of lines) {
|
|
71
|
+
const line = rawLine.trim();
|
|
72
|
+
if (line) {
|
|
73
|
+
if (line.startsWith("TOKEN:") && (authTokenFromServer = line.substring(6), logDebug(`Received auth token from server: ${authTokenFromServer.substring(0, 8)}...`), serverStartupShown && authEnabled && authTokenFromServer && (console.log(ansis.cyan(` Access URL: http://localhost:${port}?token=${authTokenFromServer}`)), console.log(ansis.dim(` Auth token: ${authTokenFromServer}`)), !options.noBrowser)))
|
|
74
|
+
try {
|
|
75
|
+
const command = getOpenCommand(), url = `http://localhost:${port}?token=${authTokenFromServer}`;
|
|
76
|
+
logDebug(`Opening browser with command: ${command} ${url}`), spawn(command, [url], {
|
|
77
|
+
detached: !0,
|
|
78
|
+
stdio: "ignore"
|
|
79
|
+
});
|
|
80
|
+
} catch {
|
|
81
|
+
logVerbose("Could not auto-open browser (not critical)");
|
|
82
|
+
}
|
|
83
|
+
if (line.includes("running at http://localhost")) {
|
|
84
|
+
if (serverStartupShown = !0, isTelemetryEnabled && serverStartupSpan) {
|
|
85
|
+
logDebug("[Telemetry] Ending visualize.server.startup span (server started successfully)");
|
|
86
|
+
const { endSpan } = await import("../telemetry/index.js");
|
|
87
|
+
endSpan(serverStartupSpan), serverStartupSpan = null, logDebug("[Telemetry] Span ended");
|
|
88
|
+
}
|
|
89
|
+
if (console.log(ansis.green("\u2713 Visualization server started")), authEnabled) {
|
|
90
|
+
const token = authTokenFromServer || authToken || "(pending)";
|
|
91
|
+
authTokenFromServer ? (console.log(ansis.cyan(` Access URL: http://localhost:${port}?token=${token}`)), console.log(ansis.dim(` Auth token: ${token}`))) : (console.log(ansis.dim(` Open http://localhost:${port} in your browser`)), logDebug(" (waiting for auth token...)"));
|
|
92
|
+
} else
|
|
93
|
+
console.log(ansis.dim(` Open http://localhost:${port} in your browser`)), console.log(ansis.yellow(" \u26A0 Authentication disabled"));
|
|
94
|
+
withDanger && console.log(ansis.yellow(" \u26A0 Danger mode enabled - chat permissions will be skipped")), console.log(ansis.blueBright(`Model name: ${model.manifest.name}`));
|
|
95
|
+
const drFolder = await getSpecReferencePath();
|
|
96
|
+
console.log(`DR folder: ${ansis.cyan(drFolder || "Not found")}`), console.log(`Model path: ${ansis.cyan(await getModelPath() || "Not found")}`);
|
|
97
|
+
const shouldOpenBrowser = !options.noBrowser;
|
|
98
|
+
if (logDebug(`Browser auto-open: ${shouldOpenBrowser ? "enabled" : "disabled"} (noBrowser=${options.noBrowser})`), shouldOpenBrowser && !authEnabled)
|
|
99
|
+
try {
|
|
100
|
+
const command = getOpenCommand(), url = `http://localhost:${port}`;
|
|
101
|
+
logDebug(`Opening browser with command: ${command} ${url}`), spawn(command, [url], {
|
|
102
|
+
detached: !0,
|
|
103
|
+
stdio: "ignore"
|
|
104
|
+
});
|
|
105
|
+
} catch {
|
|
106
|
+
logVerbose("Could not auto-open browser (not critical)");
|
|
107
|
+
}
|
|
108
|
+
else shouldOpenBrowser && authEnabled && !authTokenFromServer ? logDebug("Browser auto-open deferred until token is received") : logDebug("Browser auto-open disabled");
|
|
109
|
+
}
|
|
110
|
+
line.startsWith("TOKEN:") || logDebug(`[server] ${line}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}), serverProcess.stderr && serverProcess.stderr.on("data", (data) => {
|
|
114
|
+
const output = data.toString().trim();
|
|
115
|
+
output && (serverOutput += output + `
|
|
116
|
+
`, logDebug(`[server stderr] ${output}`));
|
|
117
|
+
});
|
|
118
|
+
let rejectKeepAlive = null;
|
|
119
|
+
serverProcess.on("close", (code) => {
|
|
120
|
+
if (code !== 0) {
|
|
121
|
+
const message = serverOutput ? `Server exited with code ${code}
|
|
122
|
+
Server output:
|
|
123
|
+
${serverOutput}` : `Server exited with code ${code}`;
|
|
124
|
+
isTelemetryEnabled && serverStartupSpan && (async () => {
|
|
125
|
+
const { endSpan } = await import("../telemetry/index.js");
|
|
126
|
+
"recordException" in serverStartupSpan && (serverStartupSpan.recordException(new Error(message)), serverStartupSpan.setStatus({ code: 2, message })), endSpan(serverStartupSpan), serverStartupSpan = null;
|
|
127
|
+
})(), console.error(message);
|
|
128
|
+
const error = new CLIError(message, code || 1);
|
|
129
|
+
rejectKeepAlive && rejectKeepAlive(error);
|
|
34
130
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
131
|
+
}), serverProcess.on("error", (error) => {
|
|
132
|
+
const message = `Failed to start visualization server: ${error.message}`;
|
|
133
|
+
isTelemetryEnabled && serverStartupSpan && (async () => {
|
|
134
|
+
const { endSpan } = await import("../telemetry/index.js");
|
|
135
|
+
"recordException" in serverStartupSpan && (serverStartupSpan.recordException(error), serverStartupSpan.setStatus({ code: 2, message })), endSpan(serverStartupSpan), serverStartupSpan = null;
|
|
136
|
+
})(), console.error(message);
|
|
137
|
+
const cliError = new CLIError(message, 1);
|
|
138
|
+
rejectKeepAlive && rejectKeepAlive(cliError);
|
|
139
|
+
});
|
|
140
|
+
let flushInterval = null;
|
|
141
|
+
if (isTelemetryEnabled) {
|
|
142
|
+
logDebug("[Telemetry] Setting up periodic flush (every 15 seconds)");
|
|
143
|
+
const { flushTelemetry } = await import("../telemetry/index.js");
|
|
144
|
+
flushInterval = setInterval(async () => {
|
|
145
|
+
logDebug("[Telemetry] Periodic flush: flushing pending spans...");
|
|
146
|
+
try {
|
|
147
|
+
await flushTelemetry(), logDebug("[Telemetry] Periodic flush complete");
|
|
148
|
+
} catch (error) {
|
|
149
|
+
logDebug(`[Telemetry] Periodic flush failed: ${error}`);
|
|
150
|
+
}
|
|
151
|
+
}, 15e3);
|
|
152
|
+
}
|
|
153
|
+
const handleShutdown = async (signal) => {
|
|
154
|
+
logDebug(`
|
|
155
|
+
[${signal}] Shutting down visualization server gracefully...`), flushInterval && (logDebug("[Telemetry] Stopping periodic flush"), clearInterval(flushInterval), flushInterval = null), serverProcess && !serverProcess.killed && (logDebug("Sending termination signal to server process..."), serverProcess.kill(signal), await new Promise((resolve) => {
|
|
156
|
+
const timeout = setTimeout(() => {
|
|
157
|
+
logDebug("Server shutdown timeout, forcing exit..."), serverProcess.killed || serverProcess.kill("SIGKILL"), resolve();
|
|
158
|
+
}, 3e3);
|
|
159
|
+
serverProcess.on("exit", () => {
|
|
160
|
+
clearTimeout(timeout), resolve();
|
|
161
|
+
});
|
|
162
|
+
})), logDebug("Visualization server stopped"), process.exit(0);
|
|
163
|
+
};
|
|
164
|
+
process.on("SIGINT", () => handleShutdown("SIGINT")), process.on("SIGTERM", () => handleShutdown("SIGTERM")), await new Promise((_, reject) => {
|
|
165
|
+
rejectKeepAlive = reject;
|
|
38
166
|
});
|
|
39
167
|
} catch (error) {
|
|
40
|
-
|
|
41
|
-
|
|
168
|
+
if (error instanceof CLIError)
|
|
169
|
+
throw error;
|
|
170
|
+
const message = getErrorMessage(error);
|
|
171
|
+
throw console.error(message), new CLIError(message, 1);
|
|
42
172
|
}
|
|
43
173
|
}
|
|
44
174
|
function getOpenCommand() {
|