@documentation-robotics/cli 0.1.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -2
- package/dist/analysis/relationship-classifier.js +2 -9
- package/dist/analysis/relationship-classifier.js.map +2 -2
- package/dist/analyzers/call-graph-utils.js +2 -2
- package/dist/analyzers/call-graph-utils.js.map +2 -2
- package/dist/analyzers/cards/build.js +171 -0
- package/dist/analyzers/cards/build.js.map +7 -0
- package/dist/analyzers/cards/classify.js +42 -0
- package/dist/analyzers/cards/classify.js.map +7 -0
- package/dist/analyzers/cards/edge-index.js +44 -0
- package/dist/analyzers/cards/edge-index.js.map +7 -0
- package/dist/analyzers/cards/facts.js +46 -0
- package/dist/analyzers/cards/facts.js.map +7 -0
- package/dist/analyzers/cards/graph.js +42 -0
- package/dist/analyzers/cards/graph.js.map +7 -0
- package/dist/analyzers/cards/index.js +8 -0
- package/dist/analyzers/cards/index.js.map +7 -0
- package/dist/analyzers/cards/tier0.js +18 -0
- package/dist/analyzers/cards/tier0.js.map +7 -0
- package/dist/analyzers/cards/types.js +1 -0
- package/dist/analyzers/cards/types.js.map +7 -0
- package/dist/analyzers/cbm-analyzer.js +195 -171
- package/dist/analyzers/cbm-analyzer.js.map +2 -2
- package/dist/analyzers/cbm-responses.js +336 -0
- package/dist/analyzers/cbm-responses.js.map +7 -0
- package/dist/analyzers/edge-relationships.js +45 -0
- package/dist/analyzers/edge-relationships.js.map +7 -0
- package/dist/analyzers/mapping-loader.js +9 -0
- package/dist/analyzers/mapping-loader.js.map +2 -2
- package/dist/analyzers/tier0-rules.js +153 -0
- package/dist/analyzers/tier0-rules.js.map +7 -0
- package/dist/analyzers/types.js.map +1 -1
- package/dist/analyzers/verify-engine.js +22 -19
- package/dist/analyzers/verify-engine.js.map +2 -2
- package/dist/audit/relationships/ai/prompts.js +10 -10
- package/dist/audit/relationships/ai/prompts.js.map +2 -2
- package/dist/audit/relationships/analysis/layer-templates.js +52 -52
- package/dist/audit/relationships/analysis/layer-templates.js.map +1 -1
- package/dist/cli.js +112 -28
- package/dist/cli.js.map +3 -3
- package/dist/coding-agents/agents/claude-code.js +3 -1
- package/dist/coding-agents/agents/claude-code.js.map +2 -2
- package/dist/coding-agents/claude-code-client.js +2 -1
- package/dist/coding-agents/claude-code-client.js.map +2 -2
- package/dist/coding-agents/copilot-client.js +17 -12
- package/dist/coding-agents/copilot-client.js.map +2 -2
- package/dist/coding-agents/default-permissions.js +152 -0
- package/dist/coding-agents/default-permissions.js.map +7 -0
- package/dist/coding-agents/drbot-mcp.js +167 -0
- package/dist/coding-agents/drbot-mcp.js.map +7 -0
- package/dist/commands/add.js +12 -7
- package/dist/commands/add.js.map +2 -2
- package/dist/commands/analyzer.js +134 -23
- package/dist/commands/analyzer.js.map +2 -2
- package/dist/commands/audit.js +6 -6
- package/dist/commands/audit.js.map +2 -2
- package/dist/commands/changeset-verify.js +55 -0
- package/dist/commands/changeset-verify.js.map +7 -0
- package/dist/commands/changeset.js +261 -147
- package/dist/commands/changeset.js.map +2 -2
- package/dist/commands/delete.js +52 -19
- package/dist/commands/delete.js.map +3 -3
- package/dist/commands/element.js +3 -2
- package/dist/commands/element.js.map +2 -2
- package/dist/commands/farm.js +773 -0
- package/dist/commands/farm.js.map +7 -0
- package/dist/commands/init.js +11 -1
- package/dist/commands/init.js.map +2 -2
- package/dist/commands/mcp.js +122 -0
- package/dist/commands/mcp.js.map +7 -0
- package/dist/commands/relationship.js +251 -47
- package/dist/commands/relationship.js.map +2 -2
- package/dist/commands/reports.js +1 -1
- package/dist/commands/reports.js.map +2 -2
- package/dist/commands/update.js +56 -24
- package/dist/commands/update.js.map +2 -2
- package/dist/commands/upgrade.js +99 -11
- package/dist/commands/upgrade.js.map +3 -3
- package/dist/commands/validate.js +41 -3
- package/dist/commands/validate.js.map +2 -2
- package/dist/commands/version.js +2 -2
- package/dist/commands/version.js.map +2 -2
- package/dist/commands/visualize.js +4 -3
- package/dist/commands/visualize.js.map +2 -2
- package/dist/config.js +83 -0
- package/dist/config.js.map +7 -0
- package/dist/core/annotation-store.js +138 -0
- package/dist/core/annotation-store.js.map +7 -0
- package/dist/core/catalog-migration.js +33 -0
- package/dist/core/catalog-migration.js.map +7 -0
- package/dist/core/changeset-analysis.js +421 -0
- package/dist/core/changeset-analysis.js.map +7 -0
- package/dist/core/changeset-base-index.js +153 -0
- package/dist/core/changeset-base-index.js.map +7 -0
- package/dist/core/changeset-brief-delta.js +102 -0
- package/dist/core/changeset-brief-delta.js.map +7 -0
- package/dist/core/changeset-graph.js +281 -0
- package/dist/core/changeset-graph.js.map +7 -0
- package/dist/core/changeset-only-guard.js +32 -0
- package/dist/core/changeset-only-guard.js.map +7 -0
- package/dist/core/changeset-summary.js +68 -0
- package/dist/core/changeset-summary.js.map +7 -0
- package/dist/core/changeset-validator.js +66 -20
- package/dist/core/changeset-validator.js.map +2 -2
- package/dist/core/changeset-verify.js +518 -0
- package/dist/core/changeset-verify.js.map +7 -0
- package/dist/core/changeset.js +56 -9
- package/dist/core/changeset.js.map +2 -2
- package/dist/core/element-type-migration.js +145 -0
- package/dist/core/element-type-migration.js.map +7 -0
- package/dist/core/farm-manifest.js +140 -0
- package/dist/core/farm-manifest.js.map +7 -0
- package/dist/core/farm-sync-engine.js +346 -0
- package/dist/core/farm-sync-engine.js.map +7 -0
- package/dist/core/farm-sync-state.js +167 -0
- package/dist/core/farm-sync-state.js.map +7 -0
- package/dist/core/manifest.js +6 -3
- package/dist/core/manifest.js.map +2 -2
- package/dist/core/migration-registry.js +84 -1
- package/dist/core/migration-registry.js.map +2 -2
- package/dist/core/model-upgrade.js +102 -0
- package/dist/core/model-upgrade.js.map +7 -0
- package/dist/core/model.js +257 -44
- package/dist/core/model.js.map +3 -3
- package/dist/core/mutation-handler.js +71 -6
- package/dist/core/mutation-handler.js.map +2 -2
- package/dist/core/relationship-migration-table.js +6639 -0
- package/dist/core/relationship-migration-table.js.map +7 -0
- package/dist/core/relationship-migration.js +272 -0
- package/dist/core/relationship-migration.js.map +7 -0
- package/dist/core/relationship-prune.js +49 -0
- package/dist/core/relationship-prune.js.map +7 -0
- package/dist/core/relationship-staging.js +68 -0
- package/dist/core/relationship-staging.js.map +7 -0
- package/dist/core/relationships.js +26 -4
- package/dist/core/relationships.js.map +2 -2
- package/dist/core/report-data-model.js +7 -13
- package/dist/core/report-data-model.js.map +2 -2
- package/dist/core/staged-changeset-storage.js +64 -17
- package/dist/core/staged-changeset-storage.js.map +2 -2
- package/dist/core/staged-source-reference.js +28 -0
- package/dist/core/staged-source-reference.js.map +7 -0
- package/dist/core/staging-area.js +83 -18
- package/dist/core/staging-area.js.map +2 -2
- package/dist/core/virtual-projection.js +14 -5
- package/dist/core/virtual-projection.js.map +2 -2
- package/dist/export/archimate-exporter.js +1 -0
- package/dist/export/archimate-exporter.js.map +2 -2
- package/dist/generated/compiled-validators.js +2 -2
- package/dist/generated/compiled-validators.js.map +2 -2
- package/dist/generated/layer-registry.js +16 -16
- package/dist/generated/layer-registry.js.map +2 -2
- package/dist/generated/node-types.js +186 -168
- package/dist/generated/node-types.js.map +2 -2
- package/dist/generated/relationship-index.js +2209 -7727
- package/dist/generated/relationship-index.js.map +2 -2
- package/dist/integrations/claude_code/agents/dr-architect.md +16 -3
- package/dist/integrations/claude_code/agents/dr-extractor.md +1 -1
- package/dist/integrations/claude_code/commands/dr-analyzer.md +565 -0
- package/dist/integrations/claude_code/commands/dr-map.md +13 -0
- package/dist/integrations/claude_code/commands/dr-plan.md +40 -0
- package/dist/integrations/claude_code/commands/dr-relate.md +106 -96
- package/dist/integrations/claude_code/commands/dr-verify.md +45 -2
- package/dist/integrations/claude_code/docs/END_TO_END_WALKTHROUGH.md +14 -0
- package/dist/integrations/claude_code/docs/MCP_SERVER.md +79 -0
- package/dist/integrations/claude_code/docs/QUICK_START.md +37 -8
- package/dist/integrations/claude_code/docs/README.md +52 -1
- package/dist/integrations/claude_code/skills/dr_01_motivation_layer/SKILL.md +93 -72
- package/dist/integrations/claude_code/skills/dr_02_business_layer/SKILL.md +163 -126
- package/dist/integrations/claude_code/skills/dr_03_product_layer/SKILL.md +161 -126
- package/dist/integrations/claude_code/skills/dr_04_security_layer/SKILL.md +153 -133
- package/dist/integrations/claude_code/skills/dr_05_application_layer/SKILL.md +129 -100
- package/dist/integrations/claude_code/skills/dr_06_technology_layer/SKILL.md +111 -94
- package/dist/integrations/claude_code/skills/dr_07_api_layer/SKILL.md +143 -157
- package/dist/integrations/claude_code/skills/dr_08_data_model_layer/SKILL.md +117 -33
- package/dist/integrations/claude_code/skills/dr_09_dataset_layer/SKILL.md +74 -25
- package/dist/integrations/claude_code/skills/dr_10_ux_layer/SKILL.md +88 -12
- package/dist/integrations/claude_code/skills/dr_11_navigation_layer/SKILL.md +83 -24
- package/dist/integrations/claude_code/skills/dr_12_apm_layer/SKILL.md +57 -12
- package/dist/integrations/claude_code/skills/dr_13_testing_layer/SKILL.md +92 -15
- package/dist/integrations/claude_code/skills/dr_change_planning/SKILL.md +119 -0
- package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +3 -0
- package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +1 -1
- package/dist/integrations/github_copilot/agents/dr-architect.md +1 -1
- package/dist/integrations/github_copilot/skills/dr_01_motivation_layer/SKILL.md +182 -102
- package/dist/integrations/github_copilot/skills/dr_02_business_layer/SKILL.md +266 -148
- package/dist/integrations/github_copilot/skills/dr_03_product_layer/SKILL.md +547 -86
- package/dist/integrations/github_copilot/skills/dr_04_security_layer/SKILL.md +164 -169
- package/dist/integrations/github_copilot/skills/dr_05_application_layer/SKILL.md +420 -150
- package/dist/integrations/github_copilot/skills/dr_06_technology_layer/SKILL.md +331 -138
- package/dist/integrations/github_copilot/skills/dr_07_api_layer/SKILL.md +265 -201
- package/dist/integrations/github_copilot/skills/dr_08_data_model_layer/SKILL.md +181 -58
- package/dist/integrations/github_copilot/skills/dr_09_dataset_layer/SKILL.md +209 -57
- package/dist/integrations/github_copilot/skills/dr_10_ux_layer/SKILL.md +277 -112
- package/dist/integrations/github_copilot/skills/dr_11_navigation_layer/SKILL.md +219 -70
- package/dist/integrations/github_copilot/skills/dr_12_apm_layer/SKILL.md +189 -105
- package/dist/integrations/github_copilot/skills/dr_13_testing_layer/SKILL.md +222 -102
- package/dist/integrations/github_copilot/skills/dr_change_planning/SKILL.md +119 -0
- package/dist/integrations/github_copilot/skills/dr_changeset_reviewer/SKILL.md +3 -0
- package/dist/integrations/hash-utils.js.map +2 -2
- package/dist/mcp/api-key-manager.js +111 -0
- package/dist/mcp/api-key-manager.js.map +7 -0
- package/dist/mcp/changeset-only.js +34 -0
- package/dist/mcp/changeset-only.js.map +7 -0
- package/dist/mcp/http-transport.js +176 -0
- package/dist/mcp/http-transport.js.map +7 -0
- package/dist/mcp/resource-registry.js +97 -0
- package/dist/mcp/resource-registry.js.map +7 -0
- package/dist/mcp/tool-registry.js +60 -0
- package/dist/mcp/tool-registry.js.map +7 -0
- package/dist/mcp/tools/annotation-create.js +39 -0
- package/dist/mcp/tools/annotation-create.js.map +7 -0
- package/dist/mcp/tools/annotation-delete.js +29 -0
- package/dist/mcp/tools/annotation-delete.js.map +7 -0
- package/dist/mcp/tools/annotation-get.js +29 -0
- package/dist/mcp/tools/annotation-get.js.map +7 -0
- package/dist/mcp/tools/annotation-list.js +24 -0
- package/dist/mcp/tools/annotation-list.js.map +7 -0
- package/dist/mcp/tools/annotation-reply.js +34 -0
- package/dist/mcp/tools/annotation-reply.js.map +7 -0
- package/dist/mcp/tools/annotation-shared.js +10 -0
- package/dist/mcp/tools/annotation-shared.js.map +7 -0
- package/dist/mcp/tools/annotation-update.js +39 -0
- package/dist/mcp/tools/annotation-update.js.map +7 -0
- package/dist/mcp/tools/changeset-analysis-tools.js +78 -0
- package/dist/mcp/tools/changeset-analysis-tools.js.map +7 -0
- package/dist/mcp/tools/changeset-editing.js +184 -0
- package/dist/mcp/tools/changeset-editing.js.map +7 -0
- package/dist/mcp/tools/changeset-lifecycle.js +83 -0
- package/dist/mcp/tools/changeset-lifecycle.js.map +7 -0
- package/dist/mcp/tools/changeset-list.js +33 -0
- package/dist/mcp/tools/changeset-list.js.map +7 -0
- package/dist/mcp/tools/changeset-shared.js +31 -0
- package/dist/mcp/tools/changeset-shared.js.map +7 -0
- package/dist/mcp/tools/changeset-show.js +55 -0
- package/dist/mcp/tools/changeset-show.js.map +7 -0
- package/dist/mcp/tools/changeset-verify.js +43 -0
- package/dist/mcp/tools/changeset-verify.js.map +7 -0
- package/dist/mcp/tools/chat-launch.js +50 -0
- package/dist/mcp/tools/chat-launch.js.map +7 -0
- package/dist/mcp/tools/chat-status.js +26 -0
- package/dist/mcp/tools/chat-status.js.map +7 -0
- package/dist/mcp/tools/index.js +65 -0
- package/dist/mcp/tools/index.js.map +7 -0
- package/dist/mcp/tools/model-add.js +107 -0
- package/dist/mcp/tools/model-add.js.map +7 -0
- package/dist/mcp/tools/model-delete.js +99 -0
- package/dist/mcp/tools/model-delete.js.map +7 -0
- package/dist/mcp/tools/model-export.js +72 -0
- package/dist/mcp/tools/model-export.js.map +7 -0
- package/dist/mcp/tools/model-info.js +51 -0
- package/dist/mcp/tools/model-info.js.map +7 -0
- package/dist/mcp/tools/model-list.js +53 -0
- package/dist/mcp/tools/model-list.js.map +7 -0
- package/dist/mcp/tools/model-reload.js +34 -0
- package/dist/mcp/tools/model-reload.js.map +7 -0
- package/dist/mcp/tools/model-search.js +102 -0
- package/dist/mcp/tools/model-search.js.map +7 -0
- package/dist/mcp/tools/model-show.js +68 -0
- package/dist/mcp/tools/model-show.js.map +7 -0
- package/dist/mcp/tools/model-stats.js +22 -0
- package/dist/mcp/tools/model-stats.js.map +7 -0
- package/dist/mcp/tools/model-trace.js +118 -0
- package/dist/mcp/tools/model-trace.js.map +7 -0
- package/dist/mcp/tools/model-update.js +121 -0
- package/dist/mcp/tools/model-update.js.map +7 -0
- package/dist/mcp/tools/model-validate.js +78 -0
- package/dist/mcp/tools/model-validate.js.map +7 -0
- package/dist/mcp/tools/relationship-tools.js +98 -0
- package/dist/mcp/tools/relationship-tools.js.map +7 -0
- package/dist/mcp/tools/shared.js +126 -0
- package/dist/mcp/tools/shared.js.map +7 -0
- package/dist/mcp/tools/spec-type.js +90 -0
- package/dist/mcp/tools/spec-type.js.map +7 -0
- package/dist/reports/model-layer-report-generator.js +5 -3
- package/dist/reports/model-layer-report-generator.js.map +2 -2
- package/dist/reports/model-readme-generator.js +116 -0
- package/dist/reports/model-readme-generator.js.map +7 -0
- package/dist/reports/model-report-data.js +37 -1
- package/dist/reports/model-report-data.js.map +2 -2
- package/dist/reports/model-report-orchestrator.js +29 -6
- package/dist/reports/model-report-orchestrator.js.map +2 -2
- package/dist/reports/model-report-utils.js +9 -0
- package/dist/reports/model-report-utils.js.map +7 -0
- package/dist/schemas/bundled/analyzers/cbm.json +1186 -68
- package/dist/schemas/bundled/analyzers/manifest.json +2 -2
- package/dist/schemas/bundled/api.json +1029 -1658
- package/dist/schemas/bundled/apm.json +499 -734
- package/dist/schemas/bundled/application.json +745 -370
- package/dist/schemas/bundled/base.json +3 -220
- package/dist/schemas/bundled/business.json +452 -366
- package/dist/schemas/bundled/data-model.json +403 -383
- package/dist/schemas/bundled/data-store.json +334 -558
- package/dist/schemas/bundled/manifest.json +18 -18
- package/dist/schemas/bundled/motivation.json +349 -368
- package/dist/schemas/bundled/navigation.json +415 -731
- package/dist/schemas/bundled/product.json +325 -159
- package/dist/schemas/bundled/security.json +864 -1232
- package/dist/schemas/bundled/technology.json +574 -703
- package/dist/schemas/bundled/testing.json +718 -1643
- package/dist/schemas/bundled/ux.json +739 -1352
- package/dist/server/schemas.js +8 -0
- package/dist/server/schemas.js.map +2 -2
- package/dist/server/server.js +234 -31
- package/dist/server/server.js.map +2 -2
- package/dist/server-entry.js +2 -1
- package/dist/server-entry.js.map +2 -2
- package/dist/telemetry/config.js +2 -40
- package/dist/telemetry/config.js.map +2 -2
- package/dist/telemetry/index.js +1 -1
- package/dist/types/index.js.map +2 -2
- package/dist/utils/ansi-suppressor.js +23 -0
- package/dist/utils/ansi-suppressor.js.map +7 -0
- package/dist/utils/attribute-patch.js +41 -0
- package/dist/utils/attribute-patch.js.map +7 -0
- package/dist/utils/color-utils.js +34 -0
- package/dist/utils/color-utils.js.map +7 -0
- package/dist/utils/element-reference-shape.js +15 -1
- package/dist/utils/element-reference-shape.js.map +3 -3
- package/dist/utils/error-hints.js +29 -0
- package/dist/utils/error-hints.js.map +7 -0
- package/dist/utils/errors.js +75 -10
- package/dist/utils/errors.js.map +2 -2
- package/dist/utils/globals.js +17 -1
- package/dist/utils/globals.js.map +2 -2
- package/dist/utils/project-paths.js +50 -3
- package/dist/utils/project-paths.js.map +2 -2
- package/dist/utils/reference-path-parser.js +49 -0
- package/dist/utils/reference-path-parser.js.map +7 -0
- package/dist/utils/source-reference.js +17 -10
- package/dist/utils/source-reference.js.map +2 -2
- package/dist/utils/spec-version.js +10 -2
- package/dist/utils/spec-version.js.map +2 -2
- package/dist/validators/composed-reference-validator.js +240 -0
- package/dist/validators/composed-reference-validator.js.map +7 -0
- package/dist/validators/reference-validator.js +57 -13
- package/dist/validators/reference-validator.js.map +3 -3
- package/dist/validators/relationship-schema-validator.js +33 -5
- package/dist/validators/relationship-schema-validator.js.map +3 -3
- package/dist/validators/schema-validator.js +27 -9
- package/dist/validators/schema-validator.js.map +2 -2
- package/dist/validators/types.js.map +1 -1
- package/dist/viewer/README.md +6 -6
- package/dist/viewer/assets/main-CxzcuU_o.js +84 -0
- package/dist/viewer/assets/main-j-7ULYpm.css +1 -0
- package/dist/viewer/index.html +2 -2
- package/dist/viewer/manifest.json +10 -10
- package/dist/viewer/version.json +1 -1
- package/package.json +7 -3
- package/dist/viewer/assets/main-B7AOQXXX.js +0 -81
- package/dist/viewer/assets/main-vdrFrG7q.css +0 -1
package/dist/commands/upgrade.js
CHANGED
|
@@ -3,8 +3,11 @@ import { confirm } from "@clack/prompts";
|
|
|
3
3
|
import { findProjectRoot, getSpecReferencePath, getModelPath } from "../utils/project-paths.js";
|
|
4
4
|
import { getCliVersion, getCliBundledSpecVersion, getInstalledSpecVersion, getModelSpecVersion } from "../utils/spec-version.js";
|
|
5
5
|
import { MigrationRegistry } from "../core/migration-registry.js";
|
|
6
|
-
import { installSpecReference } from "../utils/spec-installer.js";
|
|
7
6
|
import { Model } from "../core/model.js";
|
|
7
|
+
import { pendingCatalogMigrations } from "../core/catalog-migration.js";
|
|
8
|
+
import { upgradeModel } from "../core/model-upgrade.js";
|
|
9
|
+
import { summarizeRelationshipChanges } from "../core/relationship-migration.js";
|
|
10
|
+
import { installSpecReference } from "../utils/spec-installer.js";
|
|
8
11
|
import { ClaudeIntegrationManager } from "../integrations/claude-manager.js";
|
|
9
12
|
import { CopilotIntegrationManager } from "../integrations/copilot-manager.js";
|
|
10
13
|
import { getErrorMessage } from "../utils/errors.js";
|
|
@@ -178,6 +181,9 @@ Available migrations:`));
|
|
|
178
181
|
toVersion: targetSpecVersion,
|
|
179
182
|
details: migrationDetails
|
|
180
183
|
});
|
|
184
|
+
} else {
|
|
185
|
+
const catalogAction = await buildCatalogAction(projectRoot, targetSpecVersion);
|
|
186
|
+
catalogAction && actions.push(catalogAction);
|
|
181
187
|
}
|
|
182
188
|
const { actions: integrationActions, upToDate: integrationUpToDate } = await buildIntegrationActions(cliVersion, options.force ?? !1);
|
|
183
189
|
if (actions.push(...integrationActions), actions.length === 0) {
|
|
@@ -259,6 +265,27 @@ async function executeSpecUpgrade(projectRoot, action) {
|
|
|
259
265
|
endSpan(operationSpan);
|
|
260
266
|
}
|
|
261
267
|
}
|
|
268
|
+
async function buildCatalogAction(projectRoot, version) {
|
|
269
|
+
let pending;
|
|
270
|
+
try {
|
|
271
|
+
pending = await pendingCatalogMigrations(await Model.load(projectRoot, { lazyLoad: !1 }));
|
|
272
|
+
} catch (error) {
|
|
273
|
+
return console.log(ansis.yellow(`\u26A0 Could not check the model against the catalog: ${getErrorMessage(error)}`)), null;
|
|
274
|
+
}
|
|
275
|
+
const details = [
|
|
276
|
+
...pending.elementTypes > 0 ? [`Rename ${pending.elementTypes} element(s) whose type was renamed`] : [],
|
|
277
|
+
...pending.relationships > 0 ? [`Rewrite or drop ${pending.relationships} relationship(s) of retired types`] : [],
|
|
278
|
+
...pending.stagedRelationships > 0 ? [`Rewrite ${pending.stagedRelationships} staged relationship change(s)`] : []
|
|
279
|
+
];
|
|
280
|
+
return details.length === 0 ? null : {
|
|
281
|
+
type: "model",
|
|
282
|
+
description: `Apply catalog changes to the model (spec v${version})`,
|
|
283
|
+
fromVersion: version,
|
|
284
|
+
toVersion: version,
|
|
285
|
+
details,
|
|
286
|
+
catalogOnly: !0
|
|
287
|
+
};
|
|
288
|
+
}
|
|
262
289
|
async function executeModelMigration(action, options) {
|
|
263
290
|
const operationSpan = isTelemetryEnabled ? startSpan("upgrade.model", {
|
|
264
291
|
"upgrade.model.from_version": action.fromVersion || "unknown",
|
|
@@ -269,20 +296,24 @@ async function executeModelMigration(action, options) {
|
|
|
269
296
|
try {
|
|
270
297
|
if (action.versionBumpOnly) {
|
|
271
298
|
console.log(ansis.dim(`Bumping model spec version from v${action.fromVersion} to v${action.toVersion}...`));
|
|
272
|
-
const
|
|
273
|
-
|
|
299
|
+
const result2 = await upgradeModel(process.cwd(), {
|
|
300
|
+
fromVersion: action.fromVersion,
|
|
301
|
+
toVersion: action.toVersion,
|
|
302
|
+
versionBumpOnly: !0
|
|
303
|
+
});
|
|
304
|
+
console.log(ansis.green(`\u2713 Model spec version updated to v${action.toVersion}`)), printChangesetRebaseline(result2.changesets), operationSpan && (operationSpan.setAttribute("upgrade.model.result", "version_bumped"), operationSpan.setAttribute("upgrade.model.changesets_rebaselined", result2.changesets.rebaselined.length));
|
|
274
305
|
return;
|
|
275
306
|
}
|
|
276
|
-
console.log(ansis.dim(`Migrating model from v${action.fromVersion} to v${action.toVersion}...`));
|
|
277
|
-
const
|
|
307
|
+
console.log(ansis.dim(action.catalogOnly ? `Applying catalog changes to the model (v${action.toVersion})...` : `Migrating model from v${action.fromVersion} to v${action.toVersion}...`));
|
|
308
|
+
const result = await upgradeModel(process.cwd(), {
|
|
278
309
|
fromVersion: action.fromVersion,
|
|
279
310
|
toVersion: action.toVersion,
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
});
|
|
283
|
-
for (const
|
|
284
|
-
console.log(ansis.green(` \u2713 ${
|
|
285
|
-
|
|
311
|
+
validate: !options.force,
|
|
312
|
+
catalogOnly: action.catalogOnly
|
|
313
|
+
}), applied = result.migration?.applied ?? [];
|
|
314
|
+
for (const migration of applied)
|
|
315
|
+
console.log(ansis.green(` \u2713 ${migration.from} \u2192 ${migration.to}: ${migration.description}`)), migration.changes?.filesModified && console.log(ansis.dim(` Files modified: ${migration.changes.filesModified}`)), printElementTypeChanges(migration.changes?.details?.elementTypeChanges), printRelationshipChanges(migration.changes?.details?.relationshipChanges), printStagedRelationshipChanges(migration.changes?.details?.stagedRelationshipChanges);
|
|
316
|
+
console.log(ansis.green(action.catalogOnly ? `\u2713 Model in line with the v${action.toVersion} catalog` : `\u2713 Model migrated to v${action.toVersion}`)), printChangesetRebaseline(result.changesets), operationSpan && (operationSpan.setAttribute("upgrade.model.result", "migrated"), operationSpan.setAttribute("upgrade.model.migrations_applied", applied.length), operationSpan.setAttribute("upgrade.model.changesets_rebaselined", result.changesets.rebaselined.length));
|
|
286
317
|
} catch (error) {
|
|
287
318
|
throw operationSpan && (operationSpan.recordException(error), operationSpan.setStatus({
|
|
288
319
|
code: 2,
|
|
@@ -293,6 +324,63 @@ async function executeModelMigration(action, options) {
|
|
|
293
324
|
endSpan(operationSpan);
|
|
294
325
|
}
|
|
295
326
|
}
|
|
327
|
+
function printElementTypeChanges(changes) {
|
|
328
|
+
if (!Array.isArray(changes) || changes.length === 0)
|
|
329
|
+
return;
|
|
330
|
+
const byType = /* @__PURE__ */ new Map();
|
|
331
|
+
for (const c of changes) {
|
|
332
|
+
const key = `${c.fromType} \u2192 ${c.toType}`;
|
|
333
|
+
byType.set(key, (byType.get(key) ?? 0) + 1);
|
|
334
|
+
}
|
|
335
|
+
for (const [key, n] of byType)
|
|
336
|
+
console.log(ansis.dim(` Renamed ${n} element(s): ${key}`));
|
|
337
|
+
}
|
|
338
|
+
function printRelationshipChanges(changes) {
|
|
339
|
+
if (!Array.isArray(changes) || changes.length === 0)
|
|
340
|
+
return;
|
|
341
|
+
const relationshipChanges = changes;
|
|
342
|
+
console.log(ansis.dim(` ${summarizeRelationshipChanges(relationshipChanges)}`));
|
|
343
|
+
for (const change of relationshipChanges)
|
|
344
|
+
change.action === "dropped-duplicate" && change.after ? console.log(ansis.dim(` dropped ${formatRelationship(change.before)} (now the same as ${formatRelationship(change.after)})`)) : change.action === "dropped" && console.log(ansis.dim(` dropped ${formatRelationship(change.before)} (no replacement in the catalog)`));
|
|
345
|
+
}
|
|
346
|
+
function printStagedRelationshipChanges(changes) {
|
|
347
|
+
if (!Array.isArray(changes) || changes.length === 0)
|
|
348
|
+
return;
|
|
349
|
+
const byChangeset = /* @__PURE__ */ new Map();
|
|
350
|
+
for (const change of changes)
|
|
351
|
+
byChangeset.set(change.changeset, [...byChangeset.get(change.changeset) ?? [], change]);
|
|
352
|
+
for (const [changeset, staged] of byChangeset) {
|
|
353
|
+
console.log(ansis.dim(` ${summarizeRelationshipChanges(staged, `changeset ${changeset}, staged relationships`)}`));
|
|
354
|
+
for (const change of staged) {
|
|
355
|
+
if (change.action === "rewritten")
|
|
356
|
+
continue;
|
|
357
|
+
const kind = change.stagedAs === "relationship-add" ? "add" : "delete";
|
|
358
|
+
console.log(ansis.dim(` dropped staged ${kind} of ${formatRelationship(change.before)} (${stagedDropReason(change)})`));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function stagedDropReason(change) {
|
|
363
|
+
if (change.action === "dropped" || !change.after)
|
|
364
|
+
return "no replacement in the catalog";
|
|
365
|
+
const sameAs = `now the same as ${formatRelationship(change.after)}`;
|
|
366
|
+
switch (change.duplicateOf) {
|
|
367
|
+
case "model":
|
|
368
|
+
return `${sameAs}, already in the model`;
|
|
369
|
+
case "kept":
|
|
370
|
+
return `${sameAs}, which also stands for a relationship the changeset keeps`;
|
|
371
|
+
default:
|
|
372
|
+
return change.stagedAs === "relationship-add" ? `${sameAs}, which the changeset already adds` : `${sameAs}, which the changeset already deletes`;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
function formatRelationship(rel) {
|
|
376
|
+
return `${rel.source} --[${rel.predicate}]--> ${rel.target}`;
|
|
377
|
+
}
|
|
378
|
+
function printChangesetRebaseline(result) {
|
|
379
|
+
const names = (refs) => refs.map((ref) => ref.name).join(", "), count = (n) => `${n} staged changeset${n === 1 ? "" : "s"}`;
|
|
380
|
+
result.rebaselined.length > 0 && console.log(ansis.green(`\u2713 Re-baselined ${count(result.rebaselined.length)} on the upgraded model: ${names(result.rebaselined)}`)), result.drifted.length > 0 && console.log(ansis.yellow(`\u26A0 ${count(result.drifted.length)} had drifted from the model before the upgrade and still ${result.drifted.length === 1 ? "needs" : "need"} --force to commit: ${names(result.drifted)}`));
|
|
381
|
+
for (const error of result.errors)
|
|
382
|
+
console.log(ansis.yellow(`\u26A0 ${error}`));
|
|
383
|
+
}
|
|
296
384
|
async function executeIntegrationUpdate(label, updateFn) {
|
|
297
385
|
const operationSpan = isTelemetryEnabled ? startSpan("upgrade.integration", {
|
|
298
386
|
"upgrade.integration.label": label,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/upgrade.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Upgrade Command - Manages spec reference and model upgrades\n *\n * Scans the filesystem to determine what needs upgrading:\n * 1. .dr/ (spec reference) - if CLI has newer bundled version\n * 2. Model data - if model spec version doesn't match spec reference\n *\n * Shows upgrade plan and prompts for confirmation before proceeding.\n */\n\nimport ansis from \"ansis\";\nimport { confirm } from \"@clack/prompts\";\nimport { findProjectRoot, getSpecReferencePath, getModelPath } from \"../utils/project-paths.js\";\nimport {\n getCliVersion,\n getCliBundledSpecVersion,\n getInstalledSpecVersion,\n getModelSpecVersion,\n} from \"../utils/spec-version.js\";\nimport { MigrationRegistry } from \"../core/migration-registry.js\";\nimport { installSpecReference } from \"../utils/spec-installer.js\";\nimport { Model } from \"../core/model.js\";\nimport { ClaudeIntegrationManager } from \"../integrations/claude-manager.js\";\nimport { CopilotIntegrationManager } from \"../integrations/copilot-manager.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { startSpan, endSpan } from \"../telemetry/index.js\";\nimport { hasLayerReports, regenerateLayerReports } from \"./reports.js\";\n\n// Build-time constant for telemetry feature detection\ndeclare const TELEMETRY_ENABLED: boolean | undefined;\nconst isTelemetryEnabled = typeof TELEMETRY_ENABLED !== \"undefined\" ? TELEMETRY_ENABLED : false;\n\nexport interface UpgradeOptions {\n yes?: boolean;\n dryRun?: boolean;\n force?: boolean;\n}\n\ninterface UpgradeAction {\n type: \"spec\" | \"model\" | \"integration\";\n description: string;\n fromVersion?: string;\n toVersion: string;\n details?: string[];\n integrationName?: \"claude\" | \"copilot\";\n versionBumpOnly?: boolean;\n}\n\n/**\n * Build integration upgrade actions and collect up-to-date status lines\n */\nasync function buildIntegrationActions(\n cliVersion: string,\n force: boolean\n): Promise<{ actions: UpgradeAction[]; upToDate: string[] }> {\n const actions: UpgradeAction[] = [];\n const upToDate: string[] = [];\n\n // Check Claude integration\n const claudeManager = new ClaudeIntegrationManager();\n if (await claudeManager.isInstalled()) {\n const claudeVersion = await claudeManager.loadVersionFile();\n const installedVersion = claudeVersion?.version;\n const needsUpgrade = installedVersion && installedVersion !== cliVersion;\n\n if (force || needsUpgrade) {\n actions.push({\n type: \"integration\",\n description: force\n ? \"Reinstall Claude Code integration (forced)\"\n : \"Upgrade Claude Code integration\",\n fromVersion: installedVersion,\n toVersion: cliVersion,\n integrationName: \"claude\",\n });\n } else if (installedVersion) {\n upToDate.push(\n ` ${ansis.green(\"\u2713\")} Claude Code integration up to date (v${installedVersion})`\n );\n }\n }\n\n // Check Copilot integration\n const copilotManager = new CopilotIntegrationManager();\n if (await copilotManager.isInstalled()) {\n const copilotVersion = await copilotManager.loadVersionFile();\n const installedVersion = copilotVersion?.version;\n const needsUpgrade = installedVersion && installedVersion !== cliVersion;\n\n if (force || needsUpgrade) {\n actions.push({\n type: \"integration\",\n description: force\n ? \"Reinstall GitHub Copilot integration (forced)\"\n : \"Upgrade GitHub Copilot integration\",\n fromVersion: installedVersion,\n toVersion: cliVersion,\n integrationName: \"copilot\",\n });\n } else if (installedVersion) {\n upToDate.push(\n ` ${ansis.green(\"\u2713\")} GitHub Copilot integration up to date (v${installedVersion})`\n );\n }\n }\n\n return { actions, upToDate };\n}\n\n/**\n * Check if layer reports exist; if not, offer to generate them.\n * Defaults to generating (yes) \u2014 including in non-interactive/programmatic mode.\n */\nasync function checkAndGenerateReports(\n projectRoot: string,\n options: UpgradeOptions\n): Promise<void> {\n if (await hasLayerReports(projectRoot)) {\n return;\n }\n\n console.log(ansis.yellow(\"\\n\u26A0 No layer reports found\"));\n\n if (options.dryRun) {\n console.log(ansis.yellow(\"[DRY RUN] Would generate all 13 layer reports\\n\"));\n return;\n }\n\n // Determine whether to generate: default is yes\n let shouldGenerate: boolean;\n const isInteractive = process.stdin.isTTY && process.stdout.isTTY;\n\n if (options.yes) {\n shouldGenerate = true;\n } else if (isInteractive) {\n const response = await confirm({\n message: \"Generate layer reports?\",\n initialValue: true,\n });\n shouldGenerate = response === true;\n } else {\n // Non-interactive / programmatic: auto-generate since default is yes\n shouldGenerate = true;\n }\n\n if (!shouldGenerate) {\n console.log(ansis.dim(\"Skipping report generation\\n\"));\n return;\n }\n\n try {\n console.log();\n await regenerateLayerReports(projectRoot);\n } catch (error) {\n // Warn but don't block upgrade success\n console.warn(ansis.yellow(`\\n\u26A0 Failed to generate reports: ${getErrorMessage(error)}\\n`));\n }\n}\n\nexport async function upgradeCommand(options: UpgradeOptions = {}): Promise<void> {\n const commandSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.execute\", {\n \"upgrade.yes\": options.yes || false,\n \"upgrade.dry_run\": options.dryRun || false,\n \"upgrade.force\": options.force || false,\n })\n : null;\n\n try {\n console.log(ansis.bold(\"\\nScanning for available upgrades...\\n\"));\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n const error = new Error(\"No DR project found. Run \\\"dr init\\\" to create a new project\");\n if (commandSpan) {\n commandSpan.recordException(error);\n commandSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: error.message,\n });\n commandSpan.setAttribute(\"upgrade.result\", \"no_project\");\n }\n console.error(ansis.red(\"Error: No DR project found\"));\n console.error(ansis.dim('Run \"dr init\" to create a new project'));\n throw error;\n }\n\n const bundledSpecVersion = getCliBundledSpecVersion();\n const cliVersion = getCliVersion();\n const actions: UpgradeAction[] = [];\n\n // ============================================================================\n // STEP 1: Check spec reference (.dr/ folder)\n // ============================================================================\n\n const drPath = await getSpecReferencePath();\n let currentSpecVersion: string | null = null;\n\n if (!drPath) {\n actions.push({\n type: \"spec\",\n description: \"Install spec reference\",\n toVersion: bundledSpecVersion,\n details: [\n \"Create .dr/ folder\",\n \"Install schema files\",\n `Set spec version to ${bundledSpecVersion}`,\n ],\n });\n } else {\n let installedSpecVersion: string | null = null;\n try {\n installedSpecVersion = await getInstalledSpecVersion(drPath);\n } catch (error) {\n // Manifest file exists but is corrupted or unreadable\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n throw error;\n }\n currentSpecVersion = installedSpecVersion;\n\n if (!installedSpecVersion) {\n actions.push({\n type: \"spec\",\n description: \"Reinstall spec reference (manifest missing)\",\n toVersion: bundledSpecVersion,\n details: [\n \"Recreate .dr/manifest.json\",\n \"Update schema files\",\n `Set spec version to ${bundledSpecVersion}`,\n ],\n });\n } else if (installedSpecVersion !== bundledSpecVersion || options.force) {\n actions.push({\n type: \"spec\",\n description: installedSpecVersion !== bundledSpecVersion\n ? \"Upgrade spec reference\"\n : \"Reinstall spec reference (forced)\",\n fromVersion: installedSpecVersion,\n toVersion: bundledSpecVersion,\n details: [\"Update schema files\", \"Update .dr/manifest.json\"],\n });\n }\n }\n\n // ============================================================================\n // STEP 2: Check model upgrade\n // ============================================================================\n\n const modelPath = await getModelPath();\n if (!modelPath) {\n console.log(ansis.yellow(\"\u26A0 No model found\"));\n console.log(ansis.dim(' Run \"dr init\" to create a model\\n'));\n\n // If only spec needs upgrade, handle it\n if (actions.length > 0) {\n const { actions: integrationActions, upToDate: integrationUpToDate } =\n await buildIntegrationActions(cliVersion, options.force ?? false);\n actions.push(...integrationActions);\n await handleUpgrade(projectRoot, actions, options, integrationUpToDate, commandSpan);\n }\n // No model loaded \u2014 report generation not applicable\n return;\n }\n\n let modelSpecVersion: string | null = null;\n try {\n modelSpecVersion = await getModelSpecVersion(modelPath);\n } catch (error) {\n // Manifest file exists but is corrupted or unreadable\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n throw error;\n }\n\n if (!modelSpecVersion) {\n console.log(ansis.yellow(\"\u26A0 Model manifest.yaml not found or missing specVersion\"));\n console.log(ansis.dim(\" Check documentation_robotics/model/manifest.yaml\\n\"));\n\n // If only spec needs upgrade, handle it\n if (actions.length > 0) {\n const { actions: integrationActions, upToDate: integrationUpToDate } =\n await buildIntegrationActions(cliVersion, options.force ?? false);\n actions.push(...integrationActions);\n await handleUpgrade(projectRoot, actions, options, integrationUpToDate, commandSpan);\n }\n // No readable model manifest \u2014 report generation not applicable\n return;\n }\n\n // Determine target spec version for model\n const targetSpecVersion = currentSpecVersion || bundledSpecVersion;\n\n if (modelSpecVersion !== targetSpecVersion) {\n // Check if we have a migration path\n const registry = new MigrationRegistry();\n const summary = registry.getMigrationSummary(modelSpecVersion, targetSpecVersion);\n\n if (summary.migrationsNeeded === 0) {\n if (options.force) {\n // No migration path exists, but --force allows bumping the model version directly.\n // This is safe for additive spec changes (new node types / relationships) that\n // require no structural data changes.\n actions.push({\n type: \"model\",\n description: \"Force-update model spec version (no migration required)\",\n fromVersion: modelSpecVersion,\n toVersion: targetSpecVersion,\n details: [\"Update manifest.yaml specVersion (no data changes needed)\"],\n versionBumpOnly: true,\n });\n } else {\n const error = new Error(\n `No migration path found from model v${modelSpecVersion} to v${targetSpecVersion}`\n );\n if (commandSpan) {\n commandSpan.recordException(error);\n commandSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: error.message,\n });\n commandSpan.setAttribute(\"upgrade.result\", \"no_migration_path\");\n }\n console.log(\n ansis.yellow(\n `\u26A0 No migration path found from model v${modelSpecVersion} to v${targetSpecVersion}`\n )\n );\n console.log(ansis.dim(\"\\nAvailable migrations:\"));\n const allMigrations = registry.getMigrationSummary(\"0.5.0\").migrations;\n for (const migration of allMigrations) {\n console.log(\n ansis.dim(` \u2022 ${migration.from} \u2192 ${migration.to}: ${migration.description}`)\n );\n }\n console.log();\n throw error;\n }\n }\n\n const migrationDetails = summary.migrations.map(\n (m) => `${m.from} \u2192 ${m.to}: ${m.description}`\n );\n\n actions.push({\n type: \"model\",\n description: \"Migrate model data\",\n fromVersion: modelSpecVersion,\n toVersion: targetSpecVersion,\n details: migrationDetails,\n });\n }\n\n // ============================================================================\n // STEP 3: Check integration versions\n // ============================================================================\n\n const { actions: integrationActions, upToDate: integrationUpToDate } =\n await buildIntegrationActions(cliVersion, options.force ?? false);\n actions.push(...integrationActions);\n\n // ============================================================================\n // STEP 4: Display upgrade plan and execute\n // ============================================================================\n\n if (actions.length === 0) {\n if (commandSpan) {\n commandSpan.setAttribute(\"upgrade.result\", \"up_to_date\");\n commandSpan.setAttribute(\"upgrade.actions_count\", 0);\n }\n console.log(ansis.green(\"\u2713 Everything is up to date!\\n\"));\n console.log(ansis.dim(` Spec reference: v${currentSpecVersion || bundledSpecVersion}`));\n console.log(ansis.dim(` Model: v${modelSpecVersion}\\n`));\n await checkAndGenerateReports(projectRoot, options);\n return;\n }\n\n if (commandSpan) {\n commandSpan.setAttribute(\"upgrade.actions_count\", actions.length);\n commandSpan.setAttribute(\n \"upgrade.has_spec_upgrade\",\n actions.some((a) => a.type === \"spec\")\n );\n commandSpan.setAttribute(\n \"upgrade.has_model_migration\",\n actions.some((a) => a.type === \"model\")\n );\n commandSpan.setAttribute(\n \"upgrade.has_integration_upgrade\",\n actions.some((a) => a.type === \"integration\")\n );\n }\n\n await handleUpgrade(projectRoot, actions, options, integrationUpToDate, commandSpan);\n await checkAndGenerateReports(projectRoot, options);\n\n if (commandSpan) {\n commandSpan.setAttribute(\"upgrade.result\", \"success\");\n }\n } catch (error) {\n if (commandSpan) {\n commandSpan.recordException(error as Error);\n commandSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n commandSpan.setAttribute(\"upgrade.result\", \"error\");\n }\n console.error(ansis.red(`Error: ${getErrorMessage(error)}`));\n throw error;\n } finally {\n endSpan(commandSpan);\n }\n}\n\n/**\n * Handle the upgrade process\n */\nasync function handleUpgrade(\n projectRoot: string,\n actions: UpgradeAction[],\n options: UpgradeOptions,\n integrationUpToDate: string[] = [],\n parentSpan: any = null\n): Promise<void> {\n // Display upgrade plan\n if (actions.length > 0) {\n console.log(ansis.bold(\"Upgrade Plan:\\n\"));\n\n for (const action of actions) {\n const versionChange = action.fromVersion\n ? `${action.fromVersion} \u2192 ${action.toVersion}`\n : `v${action.toVersion}`;\n\n const icon = action.type === \"spec\" ? \"\uD83D\uDCE6\" : action.type === \"integration\" ? \"\uD83D\uDD0C\" : \"\uD83D\uDD04\";\n console.log(ansis.yellow(`${icon} ${action.description}`));\n console.log(ansis.dim(` Version: ${versionChange}`));\n\n if (action.details && action.details.length > 0) {\n for (const detail of action.details) {\n console.log(ansis.dim(` \u2022 ${detail}`));\n }\n }\n console.log();\n }\n }\n\n // Display integration status for up-to-date integrations\n if (integrationUpToDate.length > 0) {\n console.log(ansis.bold(\"Integration Status:\"));\n integrationUpToDate.forEach((msg) => console.log(msg));\n console.log();\n }\n\n // Handle dry-run mode\n if (options.dryRun) {\n console.log(ansis.yellow(\"[DRY RUN] No changes will be made\\n\"));\n if (parentSpan) {\n parentSpan.setAttribute(\"upgrade.dry_run_completed\", true);\n }\n return;\n }\n\n // Prompt for confirmation unless --yes flag is set\n let shouldProceed = options.yes;\n if (!shouldProceed) {\n // Check if we're in an interactive terminal\n const isInteractive = process.stdin.isTTY && process.stdout.isTTY;\n\n if (isInteractive) {\n const response = await confirm({\n message: \"Proceed with upgrade?\",\n });\n shouldProceed = response === true;\n } else {\n const error = new Error(\"Non-interactive mode requires --yes flag to proceed with upgrade\");\n if (parentSpan) {\n parentSpan.recordException(error);\n parentSpan.setAttribute(\"upgrade.result\", \"non_interactive_abort\");\n }\n console.error(\n ansis.red(\"Error: Non-interactive mode requires --yes flag to proceed with upgrade\")\n );\n throw error;\n }\n }\n\n if (!shouldProceed) {\n console.log(ansis.dim(\"\\nUpgrade cancelled\\n\"));\n if (parentSpan) {\n parentSpan.setAttribute(\"upgrade.user_cancelled\", true);\n }\n return;\n }\n\n console.log(ansis.bold(\"\\nExecuting upgrades...\\n\"));\n\n // Execute actions in order: spec, model, then integrations\n for (const action of actions) {\n if (action.type === \"spec\") {\n await executeSpecUpgrade(projectRoot, action);\n } else if (action.type === \"model\") {\n await executeModelMigration(action, options);\n } else if (action.type === \"integration\") {\n await executeIntegrationUpdate(action.description, async () => {\n if (action.integrationName === \"claude\") {\n const m = new ClaudeIntegrationManager();\n await m.upgrade({ force: true }); // force=true skips internal prompts (user confirmed above)\n } else {\n const m = new CopilotIntegrationManager();\n await m.upgrade({ force: true });\n }\n });\n }\n }\n\n console.log(ansis.green(\"\\n\u2713 All upgrades completed successfully!\\n\"));\n}\n\n/**\n * Execute spec reference upgrade\n */\nasync function executeSpecUpgrade(projectRoot: string, action: UpgradeAction): Promise<void> {\n const operationSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.spec\", {\n \"upgrade.spec.from_version\": action.fromVersion || \"none\",\n \"upgrade.spec.to_version\": action.toVersion,\n \"upgrade.spec.is_reinstall\": !action.fromVersion,\n })\n : null;\n\n try {\n console.log(ansis.dim(`Installing spec reference v${action.toVersion}...`));\n await installSpecReference(projectRoot, true);\n console.log(ansis.green(`\u2713 Spec reference upgraded to v${action.toVersion}`));\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.spec.result\", \"success\");\n }\n } catch (error) {\n if (operationSpan) {\n operationSpan.recordException(error as Error);\n operationSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n operationSpan.setAttribute(\"upgrade.spec.result\", \"error\");\n }\n console.error(\n ansis.red(\n `Error upgrading spec reference: ${getErrorMessage(error)}`\n )\n );\n throw error;\n } finally {\n endSpan(operationSpan);\n }\n}\n\n/**\n * Execute model migration\n */\nasync function executeModelMigration(\n action: UpgradeAction,\n options: UpgradeOptions\n): Promise<void> {\n const operationSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.model\", {\n \"upgrade.model.from_version\": action.fromVersion || \"unknown\",\n \"upgrade.model.to_version\": action.toVersion,\n \"upgrade.model.version_bump_only\": action.versionBumpOnly || false,\n \"upgrade.model.validate\": !options.force,\n })\n : null;\n\n try {\n if (action.versionBumpOnly) {\n console.log(\n ansis.dim(`Bumping model spec version from v${action.fromVersion} to v${action.toVersion}...`)\n );\n const model = await Model.load(process.cwd(), { lazyLoad: true });\n model.manifest.specVersion = action.toVersion;\n await model.saveManifest();\n console.log(ansis.green(`\u2713 Model spec version updated to v${action.toVersion}`));\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.model.result\", \"version_bumped\");\n }\n return;\n }\n\n console.log(\n ansis.dim(`Migrating model from v${action.fromVersion} to v${action.toVersion}...`)\n );\n\n // Load the model\n const model = await Model.load(process.cwd(), { lazyLoad: false });\n\n // Apply migrations\n const registry = new MigrationRegistry();\n const result = await registry.applyMigrations(model, {\n fromVersion: action.fromVersion!,\n toVersion: action.toVersion,\n dryRun: false,\n validate: !options.force,\n });\n\n // Display migration results\n for (const applied of result.applied) {\n console.log(ansis.green(` \u2713 ${applied.from} \u2192 ${applied.to}: ${applied.description}`));\n if (applied.changes?.filesModified) {\n console.log(ansis.dim(` Files modified: ${applied.changes.filesModified}`));\n }\n }\n\n // Save changes\n await model.saveManifest();\n await model.saveDirtyLayers();\n\n console.log(ansis.green(`\u2713 Model migrated to v${action.toVersion}`));\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.model.result\", \"migrated\");\n operationSpan.setAttribute(\"upgrade.model.migrations_applied\", result.applied.length);\n }\n } catch (error) {\n if (operationSpan) {\n operationSpan.recordException(error as Error);\n operationSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n operationSpan.setAttribute(\"upgrade.model.result\", \"error\");\n }\n console.error(\n ansis.red(`Error migrating model: ${getErrorMessage(error)}`)\n );\n throw error;\n } finally {\n endSpan(operationSpan);\n }\n}\n\n/**\n * Execute integration update\n */\nasync function executeIntegrationUpdate(\n label: string,\n updateFn: () => Promise<void>\n): Promise<void> {\n const operationSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.integration\", {\n \"upgrade.integration.label\": label,\n \"upgrade.integration.type\": label.includes(\"Claude\")\n ? \"claude\"\n : label.includes(\"Copilot\")\n ? \"copilot\"\n : \"unknown\",\n })\n : null;\n\n try {\n console.log(ansis.dim(`${label}...`));\n await updateFn();\n console.log(ansis.green(`\u2713 ${label}`));\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.integration.result\", \"success\");\n }\n } catch (error) {\n if (operationSpan) {\n operationSpan.recordException(error as Error);\n operationSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n operationSpan.setAttribute(\"upgrade.integration.result\", \"error\");\n }\n console.error(ansis.red(`Error: ${label} failed: ${getErrorMessage(error)}`));\n throw error;\n } finally {\n endSpan(operationSpan);\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["integrationActions", "integrationUpToDate", "
|
|
4
|
+
"sourcesContent": ["/**\n * Upgrade Command - Manages spec reference and model upgrades\n *\n * Scans the filesystem to determine what needs upgrading:\n * 1. .dr/ (spec reference) - if CLI has newer bundled version\n * 2. Model data - if model spec version doesn't match spec reference\n *\n * Shows upgrade plan and prompts for confirmation before proceeding.\n */\n\nimport ansis from \"ansis\";\nimport { confirm } from \"@clack/prompts\";\nimport { findProjectRoot, getSpecReferencePath, getModelPath } from \"../utils/project-paths.js\";\nimport {\n getCliVersion,\n getCliBundledSpecVersion,\n getInstalledSpecVersion,\n getModelSpecVersion,\n} from \"../utils/spec-version.js\";\nimport { MigrationRegistry } from \"../core/migration-registry.js\";\nimport { Model } from \"../core/model.js\";\nimport { pendingCatalogMigrations } from \"../core/catalog-migration.js\";\nimport {\n upgradeModel,\n type ChangesetRebaselineResult,\n type ChangesetRef,\n} from \"../core/model-upgrade.js\";\nimport {\n summarizeRelationshipChanges,\n type RelationshipRewriteChange,\n type StagedRelationshipRewriteChange,\n} from \"../core/relationship-migration.js\";\nimport { installSpecReference } from \"../utils/spec-installer.js\";\nimport { ClaudeIntegrationManager } from \"../integrations/claude-manager.js\";\nimport { CopilotIntegrationManager } from \"../integrations/copilot-manager.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { startSpan, endSpan } from \"../telemetry/index.js\";\nimport { hasLayerReports, regenerateLayerReports } from \"./reports.js\";\n\n// Build-time constant for telemetry feature detection\ndeclare const TELEMETRY_ENABLED: boolean | undefined;\nconst isTelemetryEnabled = typeof TELEMETRY_ENABLED !== \"undefined\" ? TELEMETRY_ENABLED : false;\n\nexport interface UpgradeOptions {\n yes?: boolean;\n dryRun?: boolean;\n force?: boolean;\n}\n\ninterface UpgradeAction {\n type: \"spec\" | \"model\" | \"integration\";\n description: string;\n fromVersion?: string;\n toVersion: string;\n details?: string[];\n integrationName?: \"claude\" | \"copilot\";\n versionBumpOnly?: boolean;\n /** Model already at the target version, but with catalog changes it has not received */\n catalogOnly?: boolean;\n}\n\n/**\n * Build integration upgrade actions and collect up-to-date status lines\n */\nasync function buildIntegrationActions(\n cliVersion: string,\n force: boolean\n): Promise<{ actions: UpgradeAction[]; upToDate: string[] }> {\n const actions: UpgradeAction[] = [];\n const upToDate: string[] = [];\n\n // Check Claude integration\n const claudeManager = new ClaudeIntegrationManager();\n if (await claudeManager.isInstalled()) {\n const claudeVersion = await claudeManager.loadVersionFile();\n const installedVersion = claudeVersion?.version;\n const needsUpgrade = installedVersion && installedVersion !== cliVersion;\n\n if (force || needsUpgrade) {\n actions.push({\n type: \"integration\",\n description: force\n ? \"Reinstall Claude Code integration (forced)\"\n : \"Upgrade Claude Code integration\",\n fromVersion: installedVersion,\n toVersion: cliVersion,\n integrationName: \"claude\",\n });\n } else if (installedVersion) {\n upToDate.push(\n ` ${ansis.green(\"\u2713\")} Claude Code integration up to date (v${installedVersion})`\n );\n }\n }\n\n // Check Copilot integration\n const copilotManager = new CopilotIntegrationManager();\n if (await copilotManager.isInstalled()) {\n const copilotVersion = await copilotManager.loadVersionFile();\n const installedVersion = copilotVersion?.version;\n const needsUpgrade = installedVersion && installedVersion !== cliVersion;\n\n if (force || needsUpgrade) {\n actions.push({\n type: \"integration\",\n description: force\n ? \"Reinstall GitHub Copilot integration (forced)\"\n : \"Upgrade GitHub Copilot integration\",\n fromVersion: installedVersion,\n toVersion: cliVersion,\n integrationName: \"copilot\",\n });\n } else if (installedVersion) {\n upToDate.push(\n ` ${ansis.green(\"\u2713\")} GitHub Copilot integration up to date (v${installedVersion})`\n );\n }\n }\n\n return { actions, upToDate };\n}\n\n/**\n * Check if layer reports exist; if not, offer to generate them.\n * Defaults to generating (yes) \u2014 including in non-interactive/programmatic mode.\n */\nasync function checkAndGenerateReports(\n projectRoot: string,\n options: UpgradeOptions\n): Promise<void> {\n if (await hasLayerReports(projectRoot)) {\n return;\n }\n\n console.log(ansis.yellow(\"\\n\u26A0 No layer reports found\"));\n\n if (options.dryRun) {\n console.log(ansis.yellow(\"[DRY RUN] Would generate all 13 layer reports\\n\"));\n return;\n }\n\n // Determine whether to generate: default is yes\n let shouldGenerate: boolean;\n const isInteractive = process.stdin.isTTY && process.stdout.isTTY;\n\n if (options.yes) {\n shouldGenerate = true;\n } else if (isInteractive) {\n const response = await confirm({\n message: \"Generate layer reports?\",\n initialValue: true,\n });\n shouldGenerate = response === true;\n } else {\n // Non-interactive / programmatic: auto-generate since default is yes\n shouldGenerate = true;\n }\n\n if (!shouldGenerate) {\n console.log(ansis.dim(\"Skipping report generation\\n\"));\n return;\n }\n\n try {\n console.log();\n await regenerateLayerReports(projectRoot);\n } catch (error) {\n // Warn but don't block upgrade success\n console.warn(ansis.yellow(`\\n\u26A0 Failed to generate reports: ${getErrorMessage(error)}\\n`));\n }\n}\n\nexport async function upgradeCommand(options: UpgradeOptions = {}): Promise<void> {\n const commandSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.execute\", {\n \"upgrade.yes\": options.yes || false,\n \"upgrade.dry_run\": options.dryRun || false,\n \"upgrade.force\": options.force || false,\n })\n : null;\n\n try {\n console.log(ansis.bold(\"\\nScanning for available upgrades...\\n\"));\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n const error = new Error(\"No DR project found. Run \\\"dr init\\\" to create a new project\");\n if (commandSpan) {\n commandSpan.recordException(error);\n commandSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: error.message,\n });\n commandSpan.setAttribute(\"upgrade.result\", \"no_project\");\n }\n console.error(ansis.red(\"Error: No DR project found\"));\n console.error(ansis.dim('Run \"dr init\" to create a new project'));\n throw error;\n }\n\n const bundledSpecVersion = getCliBundledSpecVersion();\n const cliVersion = getCliVersion();\n const actions: UpgradeAction[] = [];\n\n // ============================================================================\n // STEP 1: Check spec reference (.dr/ folder)\n // ============================================================================\n\n const drPath = await getSpecReferencePath();\n let currentSpecVersion: string | null = null;\n\n if (!drPath) {\n actions.push({\n type: \"spec\",\n description: \"Install spec reference\",\n toVersion: bundledSpecVersion,\n details: [\n \"Create .dr/ folder\",\n \"Install schema files\",\n `Set spec version to ${bundledSpecVersion}`,\n ],\n });\n } else {\n let installedSpecVersion: string | null = null;\n try {\n installedSpecVersion = await getInstalledSpecVersion(drPath);\n } catch (error) {\n // Manifest file exists but is corrupted or unreadable\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n throw error;\n }\n currentSpecVersion = installedSpecVersion;\n\n if (!installedSpecVersion) {\n actions.push({\n type: \"spec\",\n description: \"Reinstall spec reference (manifest missing)\",\n toVersion: bundledSpecVersion,\n details: [\n \"Recreate .dr/manifest.json\",\n \"Update schema files\",\n `Set spec version to ${bundledSpecVersion}`,\n ],\n });\n } else if (installedSpecVersion !== bundledSpecVersion || options.force) {\n actions.push({\n type: \"spec\",\n description: installedSpecVersion !== bundledSpecVersion\n ? \"Upgrade spec reference\"\n : \"Reinstall spec reference (forced)\",\n fromVersion: installedSpecVersion,\n toVersion: bundledSpecVersion,\n details: [\"Update schema files\", \"Update .dr/manifest.json\"],\n });\n }\n }\n\n // ============================================================================\n // STEP 2: Check model upgrade\n // ============================================================================\n\n const modelPath = await getModelPath();\n if (!modelPath) {\n console.log(ansis.yellow(\"\u26A0 No model found\"));\n console.log(ansis.dim(' Run \"dr init\" to create a model\\n'));\n\n // If only spec needs upgrade, handle it\n if (actions.length > 0) {\n const { actions: integrationActions, upToDate: integrationUpToDate } =\n await buildIntegrationActions(cliVersion, options.force ?? false);\n actions.push(...integrationActions);\n await handleUpgrade(projectRoot, actions, options, integrationUpToDate, commandSpan);\n }\n // No model loaded \u2014 report generation not applicable\n return;\n }\n\n let modelSpecVersion: string | null = null;\n try {\n modelSpecVersion = await getModelSpecVersion(modelPath);\n } catch (error) {\n // Manifest file exists but is corrupted or unreadable\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n throw error;\n }\n\n if (!modelSpecVersion) {\n console.log(ansis.yellow(\"\u26A0 Model manifest.yaml not found or missing specVersion\"));\n console.log(ansis.dim(\" Check documentation_robotics/model/manifest.yaml\\n\"));\n\n // If only spec needs upgrade, handle it\n if (actions.length > 0) {\n const { actions: integrationActions, upToDate: integrationUpToDate } =\n await buildIntegrationActions(cliVersion, options.force ?? false);\n actions.push(...integrationActions);\n await handleUpgrade(projectRoot, actions, options, integrationUpToDate, commandSpan);\n }\n // No readable model manifest \u2014 report generation not applicable\n return;\n }\n\n // Determine target spec version for model\n const targetSpecVersion = currentSpecVersion || bundledSpecVersion;\n\n if (modelSpecVersion !== targetSpecVersion) {\n // Check if we have a migration path\n const registry = new MigrationRegistry();\n const summary = registry.getMigrationSummary(modelSpecVersion, targetSpecVersion);\n\n if (summary.migrationsNeeded === 0) {\n if (options.force) {\n // No migration path exists, but --force allows bumping the model version directly.\n // This is safe for additive spec changes (new node types / relationships) that\n // require no structural data changes.\n actions.push({\n type: \"model\",\n description: \"Force-update model spec version (no migration required)\",\n fromVersion: modelSpecVersion,\n toVersion: targetSpecVersion,\n details: [\"Update manifest.yaml specVersion (no data changes needed)\"],\n versionBumpOnly: true,\n });\n } else {\n const error = new Error(\n `No migration path found from model v${modelSpecVersion} to v${targetSpecVersion}`\n );\n if (commandSpan) {\n commandSpan.recordException(error);\n commandSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: error.message,\n });\n commandSpan.setAttribute(\"upgrade.result\", \"no_migration_path\");\n }\n console.log(\n ansis.yellow(\n `\u26A0 No migration path found from model v${modelSpecVersion} to v${targetSpecVersion}`\n )\n );\n console.log(ansis.dim(\"\\nAvailable migrations:\"));\n const allMigrations = registry.getMigrationSummary(\"0.5.0\").migrations;\n for (const migration of allMigrations) {\n console.log(\n ansis.dim(` \u2022 ${migration.from} \u2192 ${migration.to}: ${migration.description}`)\n );\n }\n console.log();\n throw error;\n }\n }\n\n const migrationDetails = summary.migrations.map(\n (m) => `${m.from} \u2192 ${m.to}: ${m.description}`\n );\n\n actions.push({\n type: \"model\",\n description: \"Migrate model data\",\n fromVersion: modelSpecVersion,\n toVersion: targetSpecVersion,\n details: migrationDetails,\n });\n } else {\n // Same spec version, but the relationship catalog can change between version bumps: a\n // model stamped with the current version before a catalog change still needs it\n const catalogAction = await buildCatalogAction(projectRoot, targetSpecVersion);\n if (catalogAction) {\n actions.push(catalogAction);\n }\n }\n\n // ============================================================================\n // STEP 3: Check integration versions\n // ============================================================================\n\n const { actions: integrationActions, upToDate: integrationUpToDate } =\n await buildIntegrationActions(cliVersion, options.force ?? false);\n actions.push(...integrationActions);\n\n // ============================================================================\n // STEP 4: Display upgrade plan and execute\n // ============================================================================\n\n if (actions.length === 0) {\n if (commandSpan) {\n commandSpan.setAttribute(\"upgrade.result\", \"up_to_date\");\n commandSpan.setAttribute(\"upgrade.actions_count\", 0);\n }\n console.log(ansis.green(\"\u2713 Everything is up to date!\\n\"));\n console.log(ansis.dim(` Spec reference: v${currentSpecVersion || bundledSpecVersion}`));\n console.log(ansis.dim(` Model: v${modelSpecVersion}\\n`));\n await checkAndGenerateReports(projectRoot, options);\n return;\n }\n\n if (commandSpan) {\n commandSpan.setAttribute(\"upgrade.actions_count\", actions.length);\n commandSpan.setAttribute(\n \"upgrade.has_spec_upgrade\",\n actions.some((a) => a.type === \"spec\")\n );\n commandSpan.setAttribute(\n \"upgrade.has_model_migration\",\n actions.some((a) => a.type === \"model\")\n );\n commandSpan.setAttribute(\n \"upgrade.has_integration_upgrade\",\n actions.some((a) => a.type === \"integration\")\n );\n }\n\n await handleUpgrade(projectRoot, actions, options, integrationUpToDate, commandSpan);\n await checkAndGenerateReports(projectRoot, options);\n\n if (commandSpan) {\n commandSpan.setAttribute(\"upgrade.result\", \"success\");\n }\n } catch (error) {\n if (commandSpan) {\n commandSpan.recordException(error as Error);\n commandSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n commandSpan.setAttribute(\"upgrade.result\", \"error\");\n }\n console.error(ansis.red(`Error: ${getErrorMessage(error)}`));\n throw error;\n } finally {\n endSpan(commandSpan);\n }\n}\n\n/**\n * Handle the upgrade process\n */\nasync function handleUpgrade(\n projectRoot: string,\n actions: UpgradeAction[],\n options: UpgradeOptions,\n integrationUpToDate: string[] = [],\n parentSpan: any = null\n): Promise<void> {\n // Display upgrade plan\n if (actions.length > 0) {\n console.log(ansis.bold(\"Upgrade Plan:\\n\"));\n\n for (const action of actions) {\n const versionChange = action.fromVersion\n ? `${action.fromVersion} \u2192 ${action.toVersion}`\n : `v${action.toVersion}`;\n\n const icon = action.type === \"spec\" ? \"\uD83D\uDCE6\" : action.type === \"integration\" ? \"\uD83D\uDD0C\" : \"\uD83D\uDD04\";\n console.log(ansis.yellow(`${icon} ${action.description}`));\n console.log(ansis.dim(` Version: ${versionChange}`));\n\n if (action.details && action.details.length > 0) {\n for (const detail of action.details) {\n console.log(ansis.dim(` \u2022 ${detail}`));\n }\n }\n console.log();\n }\n }\n\n // Display integration status for up-to-date integrations\n if (integrationUpToDate.length > 0) {\n console.log(ansis.bold(\"Integration Status:\"));\n integrationUpToDate.forEach((msg) => console.log(msg));\n console.log();\n }\n\n // Handle dry-run mode\n if (options.dryRun) {\n console.log(ansis.yellow(\"[DRY RUN] No changes will be made\\n\"));\n if (parentSpan) {\n parentSpan.setAttribute(\"upgrade.dry_run_completed\", true);\n }\n return;\n }\n\n // Prompt for confirmation unless --yes flag is set\n let shouldProceed = options.yes;\n if (!shouldProceed) {\n // Check if we're in an interactive terminal\n const isInteractive = process.stdin.isTTY && process.stdout.isTTY;\n\n if (isInteractive) {\n const response = await confirm({\n message: \"Proceed with upgrade?\",\n });\n shouldProceed = response === true;\n } else {\n const error = new Error(\"Non-interactive mode requires --yes flag to proceed with upgrade\");\n if (parentSpan) {\n parentSpan.recordException(error);\n parentSpan.setAttribute(\"upgrade.result\", \"non_interactive_abort\");\n }\n console.error(\n ansis.red(\"Error: Non-interactive mode requires --yes flag to proceed with upgrade\")\n );\n throw error;\n }\n }\n\n if (!shouldProceed) {\n console.log(ansis.dim(\"\\nUpgrade cancelled\\n\"));\n if (parentSpan) {\n parentSpan.setAttribute(\"upgrade.user_cancelled\", true);\n }\n return;\n }\n\n console.log(ansis.bold(\"\\nExecuting upgrades...\\n\"));\n\n // Execute actions in order: spec, model, then integrations\n for (const action of actions) {\n if (action.type === \"spec\") {\n await executeSpecUpgrade(projectRoot, action);\n } else if (action.type === \"model\") {\n await executeModelMigration(action, options);\n } else if (action.type === \"integration\") {\n await executeIntegrationUpdate(action.description, async () => {\n if (action.integrationName === \"claude\") {\n const m = new ClaudeIntegrationManager();\n await m.upgrade({ force: true }); // force=true skips internal prompts (user confirmed above)\n } else {\n const m = new CopilotIntegrationManager();\n await m.upgrade({ force: true });\n }\n });\n }\n }\n\n console.log(ansis.green(\"\\n\u2713 All upgrades completed successfully!\\n\"));\n}\n\n/**\n * Execute spec reference upgrade\n */\nasync function executeSpecUpgrade(projectRoot: string, action: UpgradeAction): Promise<void> {\n const operationSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.spec\", {\n \"upgrade.spec.from_version\": action.fromVersion || \"none\",\n \"upgrade.spec.to_version\": action.toVersion,\n \"upgrade.spec.is_reinstall\": !action.fromVersion,\n })\n : null;\n\n try {\n console.log(ansis.dim(`Installing spec reference v${action.toVersion}...`));\n await installSpecReference(projectRoot, true);\n console.log(ansis.green(`\u2713 Spec reference upgraded to v${action.toVersion}`));\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.spec.result\", \"success\");\n }\n } catch (error) {\n if (operationSpan) {\n operationSpan.recordException(error as Error);\n operationSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n operationSpan.setAttribute(\"upgrade.spec.result\", \"error\");\n }\n console.error(\n ansis.red(\n `Error upgrading spec reference: ${getErrorMessage(error)}`\n )\n );\n throw error;\n } finally {\n endSpan(operationSpan);\n }\n}\n\n/**\n * Execute model migration\n */\n/**\n * A model action when a model at the current spec version still names element types or\n * relationship types the catalog has retired; null when it is in line with the catalog\n */\nasync function buildCatalogAction(projectRoot: string, version: string): Promise<UpgradeAction | null> {\n let pending: Awaited<ReturnType<typeof pendingCatalogMigrations>>;\n try {\n pending = await pendingCatalogMigrations(await Model.load(projectRoot, { lazyLoad: false }));\n } catch (error) {\n console.log(ansis.yellow(`\u26A0 Could not check the model against the catalog: ${getErrorMessage(error)}`));\n return null;\n }\n const details = [\n ...(pending.elementTypes > 0 ? [`Rename ${pending.elementTypes} element(s) whose type was renamed`] : []),\n ...(pending.relationships > 0 ? [`Rewrite or drop ${pending.relationships} relationship(s) of retired types`] : []),\n ...(pending.stagedRelationships > 0 ? [`Rewrite ${pending.stagedRelationships} staged relationship change(s)`] : []),\n ];\n if (details.length === 0) {\n return null;\n }\n return {\n type: \"model\",\n description: `Apply catalog changes to the model (spec v${version})`,\n fromVersion: version,\n toVersion: version,\n details,\n catalogOnly: true,\n };\n}\n\nasync function executeModelMigration(\n action: UpgradeAction,\n options: UpgradeOptions\n): Promise<void> {\n const operationSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.model\", {\n \"upgrade.model.from_version\": action.fromVersion || \"unknown\",\n \"upgrade.model.to_version\": action.toVersion,\n \"upgrade.model.version_bump_only\": action.versionBumpOnly || false,\n \"upgrade.model.validate\": !options.force,\n })\n : null;\n\n try {\n if (action.versionBumpOnly) {\n console.log(\n ansis.dim(`Bumping model spec version from v${action.fromVersion} to v${action.toVersion}...`)\n );\n const result = await upgradeModel(process.cwd(), {\n fromVersion: action.fromVersion!,\n toVersion: action.toVersion,\n versionBumpOnly: true,\n });\n console.log(ansis.green(`\u2713 Model spec version updated to v${action.toVersion}`));\n printChangesetRebaseline(result.changesets);\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.model.result\", \"version_bumped\");\n operationSpan.setAttribute(\n \"upgrade.model.changesets_rebaselined\",\n result.changesets.rebaselined.length\n );\n }\n return;\n }\n\n console.log(\n ansis.dim(\n action.catalogOnly\n ? `Applying catalog changes to the model (v${action.toVersion})...`\n : `Migrating model from v${action.fromVersion} to v${action.toVersion}...`\n )\n );\n\n // Apply migrations, save the model and re-baseline staged changesets on it\n const result = await upgradeModel(process.cwd(), {\n fromVersion: action.fromVersion!,\n toVersion: action.toVersion,\n validate: !options.force,\n catalogOnly: action.catalogOnly,\n });\n const applied = result.migration?.applied ?? [];\n\n // Display migration results\n for (const migration of applied) {\n console.log(ansis.green(` \u2713 ${migration.from} \u2192 ${migration.to}: ${migration.description}`));\n if (migration.changes?.filesModified) {\n console.log(ansis.dim(` Files modified: ${migration.changes.filesModified}`));\n }\n printElementTypeChanges(migration.changes?.details?.elementTypeChanges);\n printRelationshipChanges(migration.changes?.details?.relationshipChanges);\n printStagedRelationshipChanges(migration.changes?.details?.stagedRelationshipChanges);\n }\n\n console.log(\n ansis.green(\n action.catalogOnly\n ? `\u2713 Model in line with the v${action.toVersion} catalog`\n : `\u2713 Model migrated to v${action.toVersion}`\n )\n );\n printChangesetRebaseline(result.changesets);\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.model.result\", \"migrated\");\n operationSpan.setAttribute(\"upgrade.model.migrations_applied\", applied.length);\n operationSpan.setAttribute(\n \"upgrade.model.changesets_rebaselined\",\n result.changesets.rebaselined.length\n );\n }\n } catch (error) {\n if (operationSpan) {\n operationSpan.recordException(error as Error);\n operationSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n operationSpan.setAttribute(\"upgrade.model.result\", \"error\");\n }\n console.error(\n ansis.red(`Error migrating model: ${getErrorMessage(error)}`)\n );\n throw error;\n } finally {\n endSpan(operationSpan);\n }\n}\n\n/**\n * Report elements whose type a catalog migration renamed\n */\nfunction printElementTypeChanges(changes: unknown): void {\n if (!Array.isArray(changes) || changes.length === 0) {\n return;\n }\n const byType = new Map<string, number>();\n for (const c of changes as Array<{ fromType: string; toType: string }>) {\n const key = `${c.fromType} \u2192 ${c.toType}`;\n byType.set(key, (byType.get(key) ?? 0) + 1);\n }\n for (const [key, n] of byType) {\n console.log(ansis.dim(` Renamed ${n} element(s): ${key}`));\n }\n}\n\n/**\n * Report relationships a catalog migration rewrote, listing each one it dropped\n */\nfunction printRelationshipChanges(changes: unknown): void {\n if (!Array.isArray(changes) || changes.length === 0) {\n return;\n }\n const relationshipChanges = changes as RelationshipRewriteChange[];\n\n console.log(ansis.dim(` ${summarizeRelationshipChanges(relationshipChanges)}`));\n for (const change of relationshipChanges) {\n if (change.action === \"dropped-duplicate\" && change.after) {\n console.log(\n ansis.dim(\n ` dropped ${formatRelationship(change.before)} (now the same as ${formatRelationship(change.after)})`\n )\n );\n } else if (change.action === \"dropped\") {\n console.log(\n ansis.dim(` dropped ${formatRelationship(change.before)} (no replacement in the catalog)`)\n );\n }\n }\n}\n\n/**\n * Report staged changeset changes a catalog migration rewrote, per changeset, listing each one\n * it removed from its changeset\n */\nfunction printStagedRelationshipChanges(changes: unknown): void {\n if (!Array.isArray(changes) || changes.length === 0) {\n return;\n }\n const byChangeset = new Map<string, StagedRelationshipRewriteChange[]>();\n for (const change of changes as StagedRelationshipRewriteChange[]) {\n byChangeset.set(change.changeset, [...(byChangeset.get(change.changeset) ?? []), change]);\n }\n\n for (const [changeset, staged] of byChangeset) {\n console.log(\n ansis.dim(` ${summarizeRelationshipChanges(staged, `changeset ${changeset}, staged relationships`)}`)\n );\n for (const change of staged) {\n if (change.action === \"rewritten\") {\n continue;\n }\n const kind = change.stagedAs === \"relationship-add\" ? \"add\" : \"delete\";\n console.log(\n ansis.dim(\n ` dropped staged ${kind} of ${formatRelationship(change.before)} (${stagedDropReason(change)})`\n )\n );\n }\n }\n}\n\nfunction stagedDropReason(change: StagedRelationshipRewriteChange): string {\n if (change.action === \"dropped\" || !change.after) {\n return \"no replacement in the catalog\";\n }\n const sameAs = `now the same as ${formatRelationship(change.after)}`;\n switch (change.duplicateOf) {\n case \"model\":\n return `${sameAs}, already in the model`;\n case \"kept\":\n return `${sameAs}, which also stands for a relationship the changeset keeps`;\n default:\n return change.stagedAs === \"relationship-add\"\n ? `${sameAs}, which the changeset already adds`\n : `${sameAs}, which the changeset already deletes`;\n }\n}\n\nfunction formatRelationship(rel: { source: string; predicate: string; target: string }): string {\n return `${rel.source} --[${rel.predicate}]--> ${rel.target}`;\n}\n\n/**\n * Report the staged changesets re-baselined on the upgraded model, and those left on their old\n * base snapshot because they had drifted before the upgrade\n */\nfunction printChangesetRebaseline(result: ChangesetRebaselineResult): void {\n const names = (refs: ChangesetRef[]) => refs.map((ref) => ref.name).join(\", \");\n const count = (n: number) => `${n} staged changeset${n === 1 ? \"\" : \"s\"}`;\n\n if (result.rebaselined.length > 0) {\n console.log(\n ansis.green(\n `\u2713 Re-baselined ${count(result.rebaselined.length)} on the upgraded model: ${names(result.rebaselined)}`\n )\n );\n }\n if (result.drifted.length > 0) {\n console.log(\n ansis.yellow(\n `\u26A0 ${count(result.drifted.length)} had drifted from the model before the upgrade and still ${result.drifted.length === 1 ? \"needs\" : \"need\"} --force to commit: ${names(result.drifted)}`\n )\n );\n }\n for (const error of result.errors) {\n console.log(ansis.yellow(`\u26A0 ${error}`));\n }\n}\n\n/**\n * Execute integration update\n */\nasync function executeIntegrationUpdate(\n label: string,\n updateFn: () => Promise<void>\n): Promise<void> {\n const operationSpan = isTelemetryEnabled\n ? startSpan(\"upgrade.integration\", {\n \"upgrade.integration.label\": label,\n \"upgrade.integration.type\": label.includes(\"Claude\")\n ? \"claude\"\n : label.includes(\"Copilot\")\n ? \"copilot\"\n : \"unknown\",\n })\n : null;\n\n try {\n console.log(ansis.dim(`${label}...`));\n await updateFn();\n console.log(ansis.green(`\u2713 ${label}`));\n\n if (operationSpan) {\n operationSpan.setAttribute(\"upgrade.integration.result\", \"success\");\n }\n } catch (error) {\n if (operationSpan) {\n operationSpan.recordException(error as Error);\n operationSpan.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: getErrorMessage(error),\n });\n operationSpan.setAttribute(\"upgrade.integration.result\", \"error\");\n }\n console.error(ansis.red(`Error: ${label} failed: ${getErrorMessage(error)}`));\n throw error;\n } finally {\n endSpan(operationSpan);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["integrationActions", "integrationUpToDate", "result"]
|
|
7
7
|
}
|
|
@@ -8,6 +8,7 @@ import { ValidationFormatter } from "../validators/validation-formatter.js";
|
|
|
8
8
|
import { getErrorMessage } from "../utils/errors.js";
|
|
9
9
|
import { RELATIONSHIPS_BY_SOURCE, RELATIONSHIPS_BY_DESTINATION } from "../generated/relationship-index.js";
|
|
10
10
|
import { getActiveSpan } from "../telemetry/index.js";
|
|
11
|
+
import { StagedChangesetStorage } from "../core/staged-changeset-storage.js";
|
|
11
12
|
async function findJsonFiles(dir, baseDir = dir) {
|
|
12
13
|
const entries = await fs.readdir(dir, { withFileTypes: !0 }), files = [];
|
|
13
14
|
for (const entry of entries) {
|
|
@@ -112,9 +113,36 @@ Orphaned Elements (${stats.orphanedElements.length})`)), console.log(ansis.dim(`
|
|
|
112
113
|
const noSchemaCount = stats.orphanedElements.length - connectableCount - deadEndCount, parts = [];
|
|
113
114
|
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
115
|
}
|
|
116
|
+
async function reportStagedChangesIncluded(rootPath, changesetId, validatedLayerNames) {
|
|
117
|
+
try {
|
|
118
|
+
const changeset = await new StagedChangesetStorage(rootPath).load(changesetId);
|
|
119
|
+
if (!changeset || changeset.changes.length === 0)
|
|
120
|
+
return;
|
|
121
|
+
const validatedLayers = new Set(validatedLayerNames), relevantChangeCount = changeset.changes.filter((change) => validatedLayers.has(change.layerName)).length;
|
|
122
|
+
if (relevantChangeCount === 0)
|
|
123
|
+
return;
|
|
124
|
+
console.log(ansis.cyan(`\u2139 Including ${relevantChangeCount} staged change${relevantChangeCount === 1 ? "" : "s"} from changeset '${changesetId}'`)), console.log();
|
|
125
|
+
} catch (error) {
|
|
126
|
+
const message = getErrorMessage(error);
|
|
127
|
+
console.warn(ansis.yellow(`\u26A0 Could not load changeset '${changesetId}': ${message}`)), console.log();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function parseModelPaths(modelPathArray) {
|
|
131
|
+
const result = {};
|
|
132
|
+
if (!modelPathArray || modelPathArray.length === 0)
|
|
133
|
+
return result;
|
|
134
|
+
for (const item of modelPathArray) {
|
|
135
|
+
const [modelName, ...rest] = item.split("="), modelPath = rest.join("=");
|
|
136
|
+
if (!modelName || !modelPath)
|
|
137
|
+
throw new Error(`Invalid --model-path format: '${item}'. Expected format: 'model-name=/path/to/model'`);
|
|
138
|
+
result[modelName.trim()] = modelPath.trim();
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
115
142
|
async function validateCommand(options) {
|
|
143
|
+
options.modelPath && (options.modelPaths = parseModelPaths(options.modelPath));
|
|
116
144
|
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"));
|
|
145
|
+
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"), activeSpan.setAttribute("validate.scope", options.scope || "local"));
|
|
118
146
|
try {
|
|
119
147
|
if (options.schemas || options.schema) {
|
|
120
148
|
await validateSchemaSynchronization(), activeSpan && (activeSpan.setAttribute("validate.mode", "schema-sync"), activeSpan.setAttribute("validate.result", "success"));
|
|
@@ -124,10 +152,20 @@ async function validateCommand(options) {
|
|
|
124
152
|
if (options.orphans) {
|
|
125
153
|
activeSpan && activeSpan.setAttribute("validate.mode", "orphans-only");
|
|
126
154
|
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");
|
|
155
|
+
activeChangesetId2 && await reportStagedChangesIncluded(model.rootPath, activeChangesetId2, options.layers && options.layers.length > 0 ? options.layers : modelForOrphans.layers.keys()), await validateOrphansOnly(modelForOrphans, options.output), activeSpan && activeSpan.setAttribute("validate.result", "success");
|
|
128
156
|
return;
|
|
129
157
|
}
|
|
130
|
-
const
|
|
158
|
+
const scope = options.scope || "local", activeChangesetId = model.getActiveChangesetId(), modelToValidate = activeChangesetId ? await model.getVirtualProjectionEngine().projectModel(model, activeChangesetId) : model;
|
|
159
|
+
activeChangesetId && await reportStagedChangesIncluded(model.rootPath, activeChangesetId, options.layers && options.layers.length > 0 ? options.layers : modelToValidate.layers.keys());
|
|
160
|
+
let result;
|
|
161
|
+
if (scope === "composed") {
|
|
162
|
+
const { ComposedReferenceValidator } = await import("../validators/composed-reference-validator.js");
|
|
163
|
+
result = await new ComposedReferenceValidator(options.modelPaths || {}).validateModel(modelToValidate);
|
|
164
|
+
} else if (scope === "local")
|
|
165
|
+
result = await new Validator().validateModel(modelToValidate);
|
|
166
|
+
else
|
|
167
|
+
throw new Error(`Invalid validation scope: '${scope}'. Expected 'local' or 'composed'.`);
|
|
168
|
+
const stats = ValidationFormatter.calculateStats(modelToValidate);
|
|
131
169
|
for (const orphanId of stats.orphanedElements)
|
|
132
170
|
result.addWarning({
|
|
133
171
|
message: `Element '${orphanId}' is orphaned (no cross-layer references or intra-layer relationships)`,
|
|
@@ -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\";\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/ (15 compiled flat files) vs dist/schemas/bundled/ (same 15 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": "AAIA,OAAO,WAAW;AAClB,SAAS,YAAY,UAAU;AAC/B,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAC1B,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,yBAAyB,oCAAoC;AACtE,SAAS,qBAAqB;
|
|
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\";\nimport { StagedChangesetStorage } from \"../core/staged-changeset-storage.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 // Composed scope options\n scope?: string;\n modelPath?: string[]; // Raw array from CLI; will be parsed into modelPaths\n modelPaths?: Record<string, string>; // Parsed model-path overrides\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/ (15 compiled flat files) vs dist/schemas/bundled/ (same 15 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\n/**\n * Print a notice that staged changes from the active changeset were projected into the\n * model before validation, so users don't mistake correctly-projected staged state for\n * a validator bug. Scoped to the layers actually included in this validation run.\n */\nasync function reportStagedChangesIncluded(\n rootPath: string,\n changesetId: string,\n validatedLayerNames: Iterable<string>\n): Promise<void> {\n try {\n const changeset = await new StagedChangesetStorage(rootPath).load(changesetId);\n if (!changeset || changeset.changes.length === 0) {\n return;\n }\n\n const validatedLayers = new Set(validatedLayerNames);\n const relevantChangeCount = changeset.changes.filter((change) =>\n validatedLayers.has(change.layerName)\n ).length;\n\n if (relevantChangeCount === 0) {\n return;\n }\n\n console.log(\n ansis.cyan(\n `\u2139 Including ${relevantChangeCount} staged change${relevantChangeCount === 1 ? \"\" : \"s\"} from changeset '${changesetId}'`\n )\n );\n console.log();\n } catch (error) {\n // Changeset is corrupted or unreadable, but this is purely informational.\n // Log a warning and continue validation rather than crashing.\n const message = getErrorMessage(error);\n console.warn(ansis.yellow(`\u26A0 Could not load changeset '${changesetId}': ${message}`));\n console.log();\n }\n}\n\n/**\n * Parse model-path option strings into a dictionary\n * Format: \"model-name=/path/to/model\" (can be repeated)\n */\nfunction parseModelPaths(modelPathArray?: string[]): Record<string, string> {\n const result: Record<string, string> = {};\n\n if (!modelPathArray || modelPathArray.length === 0) {\n return result;\n }\n\n for (const item of modelPathArray) {\n const [modelName, ...rest] = item.split(\"=\");\n const modelPath = rest.join(\"=\"); // Handle paths with = in them\n\n if (!modelName || !modelPath) {\n throw new Error(\n `Invalid --model-path format: '${item}'. Expected format: 'model-name=/path/to/model'`\n );\n }\n\n result[modelName.trim()] = modelPath.trim();\n }\n\n return result;\n}\n\nexport async function validateCommand(options: ValidateOptions): Promise<void> {\n // Parse model-path options only if provided\n if (options.modelPath) {\n options.modelPaths = parseModelPaths(options.modelPath);\n }\n\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 activeSpan.setAttribute(\"validate.scope\", options.scope || \"local\");\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\n if (activeChangesetId) {\n await reportStagedChangesIncluded(\n model.rootPath,\n activeChangesetId,\n options.layers && options.layers.length > 0 ? options.layers : modelForOrphans.layers.keys()\n );\n }\n\n await validateOrphansOnly(modelForOrphans, options.output);\n\n if (activeSpan) {\n activeSpan.setAttribute(\"validate.result\", \"success\");\n }\n return;\n }\n\n // Determine validation scope and create appropriate validator\n const scope = options.scope || \"local\";\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 if (activeChangesetId) {\n await reportStagedChangesIncluded(\n model.rootPath,\n activeChangesetId,\n options.layers && options.layers.length > 0 ? options.layers : modelToValidate.layers.keys()\n );\n }\n\n let result;\n\n if (scope === \"composed\") {\n // Use composed validator for cross-model reference validation\n const { ComposedReferenceValidator } = await import(\"../validators/composed-reference-validator.js\");\n const composedValidator = new ComposedReferenceValidator(options.modelPaths || {});\n result = await composedValidator.validateModel(modelToValidate);\n } else if (scope === \"local\") {\n // Use standard validator for local validation\n const validator = new Validator();\n result = await validator.validateModel(modelToValidate);\n } else {\n throw new Error(`Invalid validation scope: '${scope}'. Expected 'local' or 'composed'.`);\n }\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": "AAIA,OAAO,WAAW;AAClB,SAAS,YAAY,UAAU;AAC/B,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAC1B,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,yBAAyB,oCAAoC;AACtE,SAAS,qBAAqB;AAC9B,SAAS,8BAA8B;AAmCvC,eAAe,cAAc,KAAa,UAAkB,KAAG;AAC7D,QAAM,UAAU,MAAM,GAAG,QAAQ,KAAK,EAAE,eAAe,GAAI,CAAE,GACvD,QAAkB,CAAA;AAExB,aAAW,SAAS,SAAS;AAC3B,UAAM,WAAW,KAAK,KAAK,KAAK,MAAM,IAAI;AAE1C,QAAI,MAAM,YAAW,KAAM,MAAM,SAAS,UAAU;AAClD,YAAM,WAAW,MAAM,cAAc,UAAU,OAAO;AACtD,YAAM,KAAK,GAAG,QAAQ;IACxB,MAAO,CAAI,MAAM,KAAK,SAAS,OAAO,KAAK,MAAM,OAAM,KAErD,MAAM,KAAK,KAAK,SAAS,SAAS,QAAQ,CAAC;EAE/C;AAEA,SAAO;AACT;AAEA,eAAe,gCAA6B;AAC1C,UAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,sCAAsC,CAAC,GAC9D,QAAQ,IAAI,EAAE;AAEd,QAAM,aAAa,cAAc,YAAY,GAAG,GAC1C,YAAY,KAAK,QAAQ,UAAU,GAGnC,cAAc,KAAK,QAAQ,WAAW,UAAU,GAGhD,gBAAgB,KAAK,KAAK,aAAa,QAAQ,MAAM,GACrD,mBAAmB,KAAK,KAAK,WAAW,oBAAoB,GAG5D,kBAAkB,MAAM,cAAc,aAAa,GACnD,qBAAqB,MAAM,cAAc,gBAAgB;AAE/D,MAAI,gBAAgB,WAAW;AAC7B,UAAM,IAAI,MAAM,wCAAwC;AAG1D,MAAI,aAAuB,CAAA;AAE3B,aAAW,cAAc,iBAAiB;AACxC,UAAM,WAAW,KAAK,KAAK,eAAe,UAAU,GAC9C,cAAc,KAAK,KAAK,kBAAkB,UAAU;AAE1D,QAAI;AACF,YAAM,cAAc,MAAM,GAAG,SAAS,UAAU,OAAO;AAEvD,UAAI;AACF,cAAM,iBAAiB,MAAM,GAAG,SAAS,aAAa,OAAO,GAGvD,aAAa,KAAK,MAAM,WAAW,GACnC,gBAAgB,KAAK,MAAM,cAAc,GACzC,iBAAiB,KAAK,UAAU,YAAY,MAAM,CAAC,GACnD,oBAAoB,KAAK,UAAU,eAAe,MAAM,CAAC;AAE/D,QAAI,mBAAmB,oBACrB,WAAW,KACT,KAAK,MAAM,IAAI,QAAG,CAAC,IAAI,UAAU,+DAA+D,IAGlG,QAAQ,IAAI,KAAK,MAAM,MAAM,QAAG,CAAC,IAAI,UAAU,EAAE;MAErD,SAAS,OAAO;AACd,YAAK,MAAc,SAAS;AAC1B,qBAAW,KACT,KAAK,MAAM,IAAI,QAAG,CAAC,IAAI,UAAU,wCAAwC;;AAG3E,gBAAM;MAEV;IACF,SAAS,OAAO;AACd,YAAM,UAAU,gBAAgB,KAAK;AACrC,iBAAW,KAAK,KAAK,MAAM,IAAI,QAAG,CAAC,IAAI,UAAU,iCAAiC,OAAO,EAAE;IAC7F;EACF;AAGA,aAAW,eAAe;AACxB,IAAK,gBAAgB,SAAS,WAAW,KACvC,WAAW,KACT,KAAK,MAAM,IAAI,QAAG,CAAC,IAAI,WAAW,0DAA0D;AAKlG,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,IAAI,EAAE,GACd,QAAQ,IACN,MAAM,KAAK,MAAM,IAAI,6CAAwC,WAAW,MAAM,YAAY,CAAC,CAAC,GAE9F,QAAQ,IAAI,EAAE;AACd,eAAW,YAAY;AACrB,cAAQ,IAAI,QAAQ;AAEtB,kBAAQ,IAAI,EAAE,GACd,QAAQ,IACN,MAAM,IAAI,gIAA2H,CAAC,GAExI,QAAQ,IAAI,EAAE,GACR,IAAI,MAAM,sCAAsC,WAAW,MAAM,WAAW;EACpF;AACE,YAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,MAAM,iCAA4B,CAAC,GACrD,QAAQ,IAAI,EAAE;AAElB;AAMA,eAAe,oBAAoB,OAAc,YAAmB;AAClE,QAAM,QAAQ,oBAAoB,eAAe,KAAK;AAEtD,MAAI,MAAM,iBAAiB,WAAW,GAAG;AAEvC,IAAI,cACF,MAAM,GAAG,UAAU,YAAY,KAAK,UAAU,EAAE,OAAO,GAAG,SAAS,CAAA,EAAE,GAAI,MAAM,CAAC,GAAG,OAAO,GAC1F,QAAQ,IAAI;4BAA+B,UAAU,EAAE,KAEvD,QAAQ,IAAI,MAAM,MAAM;+DAAY,CAAC;AAEvC;EACF;AAGA,QAAM,eAAe,oBAAI,IAAG;AAC5B,aAAW,CAAC,EAAE,KAAK,KAAK,MAAM;AAC5B,eAAW,WAAW,MAAM,aAAY,GAAI;AAE1C,YAAMA,UADK,QAAQ,QAAQ,QAAQ,IAClB,MAAM,GAAG;AAC1B,MAAIA,OAAM,UAAU,KAAG,aAAa,IAAI,GAAGA,OAAM,CAAC,CAAC,IAAIA,OAAM,CAAC,CAAC,EAAE;IACnE;AAIF,QAAM,UAAU,oBAAI,IAAG;AASvB,aAAW,aAAa,MAAM,iBAAiB,KAAI,GAAI;AACrD,UAAMA,SAAQ,UAAU,MAAM,GAAG,GAC3B,QAAQA,OAAM,CAAC,KAAK,WACpB,eAAeA,OAAM,UAAU,IAAI,GAAGA,OAAM,CAAC,CAAC,IAAIA,OAAM,CAAC,CAAC,KAAK,WAG/D,eAAe,wBAAwB,IAAI,YAAY,KAAK,CAAA,GAC5D,eAAe,CAAC,GAAG,IAAI,IAAI,aAAa,IAAI,OAAK,EAAE,qBAAqB,CAAC,CAAC,GAC1E,qBAAqB,aAAa,OAAO,OAAK,aAAa,IAAI,CAAC,CAAC,GACjE,sBAAsB,CAAC,GAAG,IAAI,IAClC,aAAa,OAAO,OAAK,mBAAmB,SAAS,EAAE,qBAAqB,CAAC,EAAE,IAAI,OAAK,EAAE,SAAS,CAAC,CACrG,GAGK,eAAe,6BAA6B,IAAI,YAAY,KAAK,CAAA,GACjE,+BAA+B,CAAC,GAAG,IAAI,IAAI,aAAa,IAAI,OAAK,EAAE,gBAAgB,CAAC,CAAC,EACxF,OAAO,OAAK,aAAa,IAAI,CAAC,CAAC,GAE5B,qBAAqB,mBAAmB,SAAS,GACjD,qBAAqB,6BAA6B,SAAS,GAC3D,gBAAgB,aAAa,SAAS,KAAK,aAAa,SAAS;AAEvE,QAAI;AACJ,IAAK,gBAEM,CAAC,sBAAsB,CAAC,qBACjC,SAAS,aAET,SAAS,gBAJT,SAAS,aAON,QAAQ,IAAI,KAAK,KAAG,QAAQ,IAAI,OAAO,CAAA,CAAE,GAC9C,QAAQ,IAAI,KAAK,EAAG,KAAK;MACvB,IAAI;MACJ,MAAM;MACN;MACA;MACA,sBAAsB;MACtB,YAAY;KACb;EACH;AAEA,MAAI,YAAY;AACd,UAAM,UAAmC;MACvC,OAAO,MAAM,iBAAiB;MAC9B,SAAS,OAAO,YACd,CAAC,GAAG,QAAQ,QAAO,CAAE,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC;;AAGlE,UAAM,GAAG,UAAU,YAAY,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,OAAO,GACxE,QAAQ,IAAI;4BAA+B,UAAU,EAAE;AACvD;EACF;AAEA,UAAQ,IAAI,MAAM,KAAK;qBAAwB,MAAM,iBAAiB,MAAM,GAAG,CAAC,GAChF,QAAQ,IAAI,MAAM,IAAI;CAA4E,CAAC;AAEnG,MAAI,eAAe,GACf,mBAAmB;AAEvB,aAAW,CAAC,WAAW,KAAK,KAAK,SAAS;AACxC,YAAQ,IAAI,MAAM,KAAK,MAAM,KAAK,KAAK,SAAS,KAAK,MAAM,MAAM,GAAG,CAAC,CAAC;AACtE,eAAW,QAAQ;AACjB,UAAI,KAAK,WAAW;AAClB,gBAAQ,IAAI,OAAO,MAAM,IAAI,QAAG,CAAC,IAAI,KAAK,EAAE,EAAE,GAC9C,QAAQ,IAAI,SAAS,MAAM,IAAI,uDAAuD,KAAK,IAAI,CAAC,EAAE;eACzF,KAAK,WAAW,YAAY;AACrC;AACA,cAAM,eAAe,KAAK,WAAW,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,KACvD,KAAK,WAAW,SAAS,IAAI,KAAK,KAAK,WAAW,SAAS,CAAC,UAAU;AACzE,gBAAQ,IAAI,OAAO,MAAM,IAAI,QAAG,CAAC,IAAI,KAAK,EAAE,IAAI,MAAM,IAAI,YAAY,CAAC,EAAE,GACzE,QAAQ,IAAI,SAAS,MAAM,IAAI,YAAY,YAAY,CAAC,EAAE;MAC5D,OAAO;AACL;AACA,cAAM,eAAe,KAAK,oBAAoB,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,GAC7D,iBAAiB,KAAK,qBAAqB,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AACtE,gBAAQ,IAAI,OAAO,MAAM,OAAO,QAAG,CAAC,IAAI,KAAK,EAAE,EAAE,GACjD,QAAQ,IAAI,SAAS,MAAM,IAAI,eAAU,YAAY,WAAM,cAAc,EAAE,CAAC,EAAE;MAChF;AAEF,YAAQ,IAAG;EACb;AAGA,QAAM,gBAAgB,MAAM,iBAAiB,SAAS,mBAAmB,cACnE,QAAkB,CAAA;AACxB,EAAI,mBAAmB,KAAG,MAAM,KAAK,GAAG,gBAAgB,cAAc,GAClE,eAAe,KAAG,MAAM,KAAK,GAAG,YAAY,mDAAmD,GAC/F,gBAAgB,KAAG,MAAM,KAAK,GAAG,aAAa,YAAY,GAC9D,QAAQ,IAAI,MAAM,IAAI,YAAY,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,cAAc,EAAE,CAAC,GACrF,mBAAmB,KACrB,QAAQ,IAAI,MAAM,IAAI,uDAAuD,CAAC;AAElF;AAOA,eAAe,4BACb,UACA,aACA,qBAAqC;AAErC,MAAI;AACF,UAAM,YAAY,MAAM,IAAI,uBAAuB,QAAQ,EAAE,KAAK,WAAW;AAC7E,QAAI,CAAC,aAAa,UAAU,QAAQ,WAAW;AAC7C;AAGF,UAAM,kBAAkB,IAAI,IAAI,mBAAmB,GAC7C,sBAAsB,UAAU,QAAQ,OAAO,CAAC,WACpD,gBAAgB,IAAI,OAAO,SAAS,CAAC,EACrC;AAEF,QAAI,wBAAwB;AAC1B;AAGF,YAAQ,IACN,MAAM,KACJ,oBAAe,mBAAmB,iBAAiB,wBAAwB,IAAI,KAAK,GAAG,oBAAoB,WAAW,GAAG,CAC1H,GAEH,QAAQ,IAAG;EACb,SAAS,OAAO;AAGd,UAAM,UAAU,gBAAgB,KAAK;AACrC,YAAQ,KAAK,MAAM,OAAO,oCAA+B,WAAW,MAAM,OAAO,EAAE,CAAC,GACpF,QAAQ,IAAG;EACb;AACF;AAMA,SAAS,gBAAgB,gBAAyB;AAChD,QAAM,SAAiC,CAAA;AAEvC,MAAI,CAAC,kBAAkB,eAAe,WAAW;AAC/C,WAAO;AAGT,aAAW,QAAQ,gBAAgB;AACjC,UAAM,CAAC,WAAW,GAAG,IAAI,IAAI,KAAK,MAAM,GAAG,GACrC,YAAY,KAAK,KAAK,GAAG;AAE/B,QAAI,CAAC,aAAa,CAAC;AACjB,YAAM,IAAI,MACR,iCAAiC,IAAI,iDAAiD;AAI1F,WAAO,UAAU,KAAI,CAAE,IAAI,UAAU,KAAI;EAC3C;AAEA,SAAO;AACT;AAEA,eAAsB,gBAAgB,SAAwB;AAE5D,EAAI,QAAQ,cACV,QAAQ,aAAa,gBAAgB,QAAQ,SAAS;AAIxD,QAAM,aAAa,cAAa;AAChC,EAAI,eACF,WAAW,aAAa,mBAAmB,QAAQ,QAAQ,KAAK,GAAG,KAAK,KAAK,GAC7E,WAAW,aAAa,mBAAmB,QAAQ,UAAU,EAAK,GAClE,WAAW,aAAa,oBAAoB,QAAQ,WAAW,EAAK,GACpE,WAAW,aAAa,oBAAoB,QAAQ,WAAW,EAAK,GACpE,WAAW,aAAa,oBAAoB,QAAQ,WAAW,QAAQ,UAAU,EAAK,GACtF,WAAW,aAAa,mBAAmB,QAAQ,UAAU,SAAS,GACtE,WAAW,aAAa,kBAAkB,QAAQ,SAAS,OAAO;AAGpE,MAAI;AAEF,QAAI,QAAQ,WAAW,QAAQ,QAAQ;AACrC,YAAM,8BAA6B,GAE/B,eACF,WAAW,aAAa,iBAAiB,aAAa,GACtD,WAAW,aAAa,mBAAmB,SAAS;AAEtD;IACF;AAGA,UAAM,QAAQ,MAAM,MAAM,KAAK,QAAQ,OAAO,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAM,IAAK,CAAA,CAAE;AAG9F,QAAI,QAAQ,SAAS;AACnB,MAAI,cACF,WAAW,aAAa,iBAAiB,cAAc;AAGzD,YAAMC,qBAAoB,MAAM,qBAAoB,GAC9C,kBAAkBA,qBACnB,MAAM,MAAM,2BAA0B,EAAG,aAAa,OAAOA,kBAAiB,IAC/E;AAEJ,MAAIA,sBACF,MAAM,4BACJ,MAAM,UACNA,oBACA,QAAQ,UAAU,QAAQ,OAAO,SAAS,IAAI,QAAQ,SAAS,gBAAgB,OAAO,KAAI,CAAE,GAIhG,MAAM,oBAAoB,iBAAiB,QAAQ,MAAM,GAErD,cACF,WAAW,aAAa,mBAAmB,SAAS;AAEtD;IACF;AAGA,UAAM,QAAQ,QAAQ,SAAS,SAGzB,oBAAoB,MAAM,qBAAoB,GAC9C,kBAAkB,oBACnB,MAAM,MAAM,2BAA0B,EAAG,aAAa,OAAO,iBAAiB,IAC/E;AAEJ,IAAI,qBACF,MAAM,4BACJ,MAAM,UACN,mBACA,QAAQ,UAAU,QAAQ,OAAO,SAAS,IAAI,QAAQ,SAAS,gBAAgB,OAAO,KAAI,CAAE;AAIhG,QAAI;AAEJ,QAAI,UAAU,YAAY;AAExB,YAAM,EAAE,2BAA0B,IAAK,MAAM,OAAO,+CAA+C;AAEnG,eAAS,MADiB,IAAI,2BAA2B,QAAQ,cAAc,CAAA,CAAE,EAChD,cAAc,eAAe;IAChE,WAAW,UAAU;AAGnB,eAAS,MADS,IAAI,UAAS,EACN,cAAc,eAAe;;AAEtD,YAAM,IAAI,MAAM,8BAA8B,KAAK,oCAAoC;AAKzF,UAAM,QAAQ,oBAAoB,eAAe,eAAe;AAChE,eAAW,YAAY,MAAM;AAC3B,aAAO,WAAW;QAChB,SAAS,YAAY,QAAQ;QAC7B,OAAO,SAAS,MAAM,GAAG,EAAE,CAAC,KAAK;QACjC,WAAW;QACX,UAAU;QACV,eAAe;OAChB;AAMH,eAAW,CAAC,WAAW,KAAK,KAAK,gBAAgB;AAC/C,iBAAW,WAAW,MAAM,aAAY,GAAI;AAC1C,cAAM,YAAY,QAAQ,QAAQ,QAAQ;AAC1C,QAAK,QAAQ,oBACX,OAAO,WAAW;UAChB,SAAS,YAAY,SAAS;UAC9B,OAAO;UACP;UACA,eACE;SACH;MAEL;AAIF,QAAI,QAAQ;AACV,iBAAW,CAAC,WAAW,KAAK,KAAK,gBAAgB;AAC/C,mBAAW,WAAW,MAAM,aAAY,GAAI;AAC1C,gBAAM,YAAY,QAAQ,QAAQ,QAAQ;AAE1C,WAAI,CAAC,QAAQ,eAAe,QAAQ,YAAY,KAAI,MAAO,OACzD,OAAO,WAAW;YAChB,SAAS,YAAY,SAAS;YAC9B,OAAO;YACP;YACA,eAAe;WAChB;QAEL;AAaJ,QARI,eACF,WAAW,aAAa,kBAAkB,OAAO,QAAO,CAAE,GAC1D,WAAW,aAAa,wBAAwB,OAAO,OAAO,MAAM,GACpE,WAAW,aAAa,0BAA0B,OAAO,SAAS,MAAM,GACxE,WAAW,aAAa,yBAAyB,MAAM,iBAAiB,MAAM,IAI5E,QAAQ,QAAQ;AAElB,UAAI;AAcJ,UAZI,QAAQ,OAAO,SAAS,KAAK,KAAK,QAAQ,OAAO,SAAS,WAAW,IACvE,UAAU,oBAAoB,WAAW,QAAQ,eAAe,IACvD,QAAQ,OAAO,SAAS,OAAO,IACxC,UAAU,KAAK,UAAU,oBAAoB,OAAO,QAAQ,eAAe,GAAG,MAAM,CAAC,IAGrF,UAAU,KAAK,UAAU,oBAAoB,OAAO,QAAQ,eAAe,GAAG,MAAM,CAAC,GAGvF,MAAM,GAAG,UAAU,QAAQ,QAAQ,SAAS,OAAO,GACnD,QAAQ,IAAI;gCAAmC,QAAQ,MAAM,EAAE,GAE3D,CAAC,OAAO,QAAO;AACjB,cAAM,IAAI,MAAM,mBAAmB;AAGrC,MAAI,cACF,WAAW,aAAa,mBAAmB,SAAS;AAEtD;IACF;AAGA,UAAM,YAAY,oBAAoB,OAAO,QAAQ,iBAAiB;MACpE,SAAS,QAAQ;MACjB,OAAO,QAAQ;KAChB;AAKD,QAHA,QAAQ,IAAI,SAAS,GAGjB,OAAO,QAAO,GAAI;AACpB,UAAI,QAAQ,UAAU,OAAO,SAAS,SAAS;AAC7C,sBAAQ,IAAI,MAAM,IAAI,kDAAkD,CAAC,GACnE,IAAI,MAAM,iCAAiC;AAGnD,MAAI,cACF,WAAW,aAAa,mBAAmB,SAAS;AAEtD;IACF;AACE,YAAM,IAAI,MAAM,mBAAmB;EAEvC,SAAS,OAAO;AACd,gBAAY,aAAa,mBAAmB,OAAO;AAEnD,UAAM,UAAU,gBAAgB,KAAK;AACrC,kBAAQ,MAAM,MAAM,IAAI,UAAU,OAAO,EAAE,CAAC,GAGxC,iBAAiB,SAAS,MAAM,UAClC,QAAQ,MAAM,MAAM,IAAI;oBAAuB,CAAC,GAChD,QAAQ,MAAM,MAAM,IAAI,MAAM,KAAK,CAAC,IAIlC,QAAQ,IAAI,UACd,QAAQ,MAAM,MAAM,IAAI;wCAA2C,CAAC,GAChE,iBAAiB,UACnB,QAAQ,MAAM,MAAM,IAAI,eAAe,MAAM,IAAI,EAAE,CAAC,GACpD,QAAQ,MAAM,MAAM,IAAI,gBAAiB,MAAc,SAAS,MAAM,EAAE,CAAC,KAKvE;EACR;AACF;",
|
|
6
6
|
"names": ["parts", "activeChangesetId"]
|
|
7
7
|
}
|
package/dist/commands/version.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import ansis from "ansis";
|
|
2
|
-
import { getCliBundledSpecVersion } from "../utils/spec-version.js";
|
|
2
|
+
import { getCliBundledSpecVersion, getCliVersion } from "../utils/spec-version.js";
|
|
3
3
|
import { isTelemetryBuiltIn, isTelemetryConfigured } from "../telemetry/detect.js";
|
|
4
4
|
import { getSpecReferencePath, getModelPath } from "../utils/project-paths.js";
|
|
5
|
-
const gitHash = "
|
|
5
|
+
const gitHash = "47d9e70", cliVersion = getCliVersion();
|
|
6
6
|
async function versionCommand() {
|
|
7
7
|
const specVersion = getCliBundledSpecVersion(), telemetryBuiltIn = isTelemetryBuiltIn(), telemetryConfigured = await isTelemetryConfigured();
|
|
8
8
|
let telemetryStatus;
|
|
@@ -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 \"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
|
|
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, getCliVersion } 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 constant (substituted by esbuild)\ndeclare const GIT_HASH: string;\n\nconst gitHash = typeof GIT_HASH !== \"undefined\" ? GIT_HASH : \"unknown\";\nconst cliVersion = getCliVersion();\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,0BAA0B,qBAAqB;AACxD,SAAS,oBAAoB,6BAA6B;AAC1D,SAAS,sBAAsB,oBAAoB;AAKnD,MAAM,UAA4C,WAC5C,aAAa,cAAa;AAEhC,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
|
}
|