@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/add.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/add.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Add an element to a layer\n */\n\nimport ansis from \"ansis\";\nimport { Model } from \"../core/model.js\";\nimport { Layer } from \"../core/layer.js\";\nimport { Element } from \"../core/element.js\";\nimport { MutationHandler } from \"../core/mutation-handler.js\";\nimport { validateSourceReferenceOptions, buildSourceReference } from \"../utils/source-reference.js\";\nimport { SchemaValidator } from \"../validators/schema-validator.js\";\nimport { getActiveSpan } from \"../telemetry/index.js\";\nimport { generateElementId, generateUUID } from \"../utils/id-generator.js\";\nimport { getAllLayerIds, isValidLayer } from \"../generated/layer-registry.js\";\nimport { isValidNodeType, getNodeTypesForLayer, normalizeNodeType } from \"../generated/node-types.js\";\nimport {\n CLIError,\n ErrorCategory,\n InvalidJSONError,\n ModelNotFoundError,\n findSimilar,\n formatValidOptions,\n getErrorMessage,\n handleError,\n handleSuccess,\n} from \"../utils/errors.js\";\n\n\nexport interface AddOptions {\n name?: string;\n description?: string;\n attributes?: string;\n sourceFile?: string;\n sourceSymbol?: string;\n sourceProvenance?: string;\n sourceRepoRemote?: string;\n sourceRepoCommit?: string;\n verbose?: boolean;\n debug?: boolean;\n}\n\nexport async function addCommand(\n layer: string,\n type: string,\n name: string,\n options: AddOptions\n): Promise<void> {\n try {\n // Validate layer name\n if (!isValidLayer(layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) {\n suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n }\n throw new CLIError(`Unknown layer \"${layer}\"`, ErrorCategory.USER, suggestions, {\n operation: \"add\",\n context: `Layer: ${layer}, Type: ${type}, Name: ${name}`,\n });\n }\n\n // Validate element type for this layer\n if (!isValidNodeType(layer, type)) {\n const validNodeTypes = getNodeTypesForLayer(layer);\n const typeNames = validNodeTypes.map((t) => t.type).sort();\n const similar = findSimilar(type, typeNames, 3);\n const suggestions: string[] = [`Valid types for ${layer}: ${formatValidOptions(typeNames)}`];\n if (similar.length > 0) {\n suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n }\n throw new CLIError(\n `Invalid element type \"${type}\" for layer \"${layer}\"`,\n ErrorCategory.USER,\n suggestions,\n {\n operation: \"add\",\n context: `Layer: ${layer}, Type: ${type}, Name: ${name}`,\n }\n );\n }\n\n // Resolve abbreviated type names to their canonical spec names\n // e.g., \"service\" \u2192 \"applicationservice\" for the application layer\n const resolvedType = normalizeNodeType(layer, type);\n\n // Generate slug path: {layer}.{resolvedType}.{kebab-name}\n const elementPath = generateElementId(layer, resolvedType, name); // slug\n const elementUUID = generateUUID(); // UUIDv4\n\n // Validate the generated slug is non-empty (name may collapse to empty after stripping special chars)\n const slugPart = elementPath.split(\".\")[2];\n if (!slugPart) {\n throw new CLIError(\n `Cannot generate a valid element ID from name \"${name}\"`,\n ErrorCategory.USER,\n [\n \"Element names must contain at least one letter or digit\",\n `Generated ID would be: ${elementPath}`,\n ]\n );\n }\n\n const span = getActiveSpan();\n span?.setAttribute(\"layer.name\", layer);\n span?.setAttribute(\"element.type\", resolvedType);\n span?.setAttribute(\"element.id\", elementPath);\n\n // Validate source reference options\n validateSourceReferenceOptions(options);\n\n // Load model (with error handling for missing models)\n let model: Model;\n try {\n model = await Model.load(
|
|
5
|
-
"mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,eAAe;AACxB,SAAS,uBAAuB;AAChC,SAAS,gCAAgC,4BAA4B;AACrE,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB,oBAAoB;AAChD,SAAS,gBAAgB,oBAAoB;AAC7C,SAAS,iBAAiB,sBAAsB,yBAAyB;AACzE,SACE,UACA,eACA,kBACA,oBACA,aACA,oBACA,iBACA,aACA,qBACK;
|
|
4
|
+
"sourcesContent": ["/**\n * Add an element to a layer\n */\n\nimport ansis from \"ansis\";\nimport { Model } from \"../core/model.js\";\nimport { Layer } from \"../core/layer.js\";\nimport { Element } from \"../core/element.js\";\nimport { MutationHandler } from \"../core/mutation-handler.js\";\nimport { validateSourceReferenceOptions, buildSourceReference } from \"../utils/source-reference.js\";\nimport { schemaLookupHint } from \"../utils/error-hints.js\";\nimport { SchemaValidator } from \"../validators/schema-validator.js\";\nimport { getActiveSpan } from \"../telemetry/index.js\";\nimport { generateElementId, generateUUID } from \"../utils/id-generator.js\";\nimport { getAllLayerIds, isValidLayer } from \"../generated/layer-registry.js\";\nimport { isValidNodeType, getNodeTypesForLayer, normalizeNodeType } from \"../generated/node-types.js\";\nimport {\n CLIError,\n ErrorCategory,\n InvalidJSONError,\n ModelNotFoundError,\n findSimilar,\n formatValidOptions,\n getErrorMessage,\n handleError,\n handleSuccess,\n} from \"../utils/errors.js\";\n\n\nexport interface AddOptions {\n model?: string;\n name?: string;\n description?: string;\n attributes?: string;\n sourceFile?: string;\n sourceSymbol?: string;\n sourceProvenance?: string;\n sourceRepoRemote?: string;\n sourceRepoCommit?: string;\n verbose?: boolean;\n debug?: boolean;\n}\n\nexport async function addCommand(\n layer: string,\n type: string,\n name: string,\n options: AddOptions\n): Promise<void> {\n try {\n // Validate layer name\n if (!isValidLayer(layer)) {\n const validLayers = getAllLayerIds();\n const similar = findSimilar(layer, validLayers, 3);\n const suggestions: string[] = [`Use a valid layer name: ${formatValidOptions(validLayers)}`];\n if (similar.length > 0) {\n suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n }\n throw new CLIError(`Unknown layer \"${layer}\"`, ErrorCategory.USER, suggestions, {\n operation: \"add\",\n context: `Layer: ${layer}, Type: ${type}, Name: ${name}`,\n });\n }\n\n // Validate element type for this layer\n if (!isValidNodeType(layer, type)) {\n const validNodeTypes = getNodeTypesForLayer(layer);\n const typeNames = validNodeTypes.map((t) => t.type).sort();\n const similar = findSimilar(type, typeNames, 3);\n const suggestions: string[] = [`Valid types for ${layer}: ${formatValidOptions(typeNames)}`];\n if (similar.length > 0) {\n suggestions.unshift(`Did you mean: ${similar.join(\" or \")}?`);\n }\n throw new CLIError(\n `Invalid element type \"${type}\" for layer \"${layer}\"`,\n ErrorCategory.USER,\n suggestions,\n {\n operation: \"add\",\n context: `Layer: ${layer}, Type: ${type}, Name: ${name}`,\n }\n );\n }\n\n // Resolve abbreviated type names to their canonical spec names\n // e.g., \"service\" \u2192 \"applicationservice\" for the application layer\n const resolvedType = normalizeNodeType(layer, type);\n\n // Generate slug path: {layer}.{resolvedType}.{kebab-name}\n const elementPath = generateElementId(layer, resolvedType, name); // slug\n const elementUUID = generateUUID(); // UUIDv4\n\n // Validate the generated slug is non-empty (name may collapse to empty after stripping special chars)\n const slugPart = elementPath.split(\".\")[2];\n if (!slugPart) {\n throw new CLIError(\n `Cannot generate a valid element ID from name \"${name}\"`,\n ErrorCategory.USER,\n [\n \"Element names must contain at least one letter or digit\",\n `Generated ID would be: ${elementPath}`,\n ]\n );\n }\n\n const span = getActiveSpan();\n span?.setAttribute(\"layer.name\", layer);\n span?.setAttribute(\"element.type\", resolvedType);\n span?.setAttribute(\"element.id\", elementPath);\n\n // Validate source reference options\n validateSourceReferenceOptions(options);\n\n // Load model (with error handling for missing models)\n let model: Model;\n try {\n model = await Model.load(options.model, { layers: [layer] });\n } catch (error) {\n const message = getErrorMessage(error);\n if (message.includes(\"No DR project\") || message.includes(\"Model not found\")) {\n throw new ModelNotFoundError();\n }\n throw error;\n }\n\n // Get or create layer\n let layerObj = await model.getLayer(layer);\n if (!layerObj) {\n layerObj = new Layer(layer);\n model.addLayer(layerObj);\n }\n\n // Parse attributes if provided\n let attributes: Record<string, unknown> = {};\n if (options.attributes) {\n try {\n attributes = JSON.parse(options.attributes);\n } catch (e) {\n throw new InvalidJSONError(options.attributes, \"--attributes\");\n }\n }\n\n // Create element in spec-node format\n // id = UUIDv4 for schema compliance; path = slug for human-readable identifier\n const element = new Element({\n id: elementUUID, // UUIDv4\n path: elementPath, // slug: {layer}.{resolvedType}.{kebab-name}\n spec_node_id: `${layer}.${resolvedType}`,\n layer_id: layer,\n type: resolvedType,\n name: options.name || name,\n description: options.description,\n attributes: attributes,\n metadata: {\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n version: 1,\n },\n layer, // Set layer so setSourceReference can use it\n });\n\n\n // Add source reference if provided\n const sourceRef = buildSourceReference(options);\n if (sourceRef) {\n element.setSourceReference(sourceRef);\n }\n\n // Validate element attributes against spec schema before persisting\n {\n const schemaValidator = new SchemaValidator();\n const tempLayer = new Layer(layer);\n tempLayer.addElement(element);\n const attrValidation = await schemaValidator.validateLayer(tempLayer);\n if (!attrValidation.isValid()) {\n const errorMessages = attrValidation.errors\n .map((e) => ` ${e.message}`)\n .join(\"\\n\");\n throw new CLIError(\n `Element ${elementPath} has invalid attributes:\\n${errorMessages}`,\n ErrorCategory.USER,\n [schemaLookupHint(\"cli\", layer, resolvedType)]\n );\n }\n }\n\n // Check if element already exists (look up by path)\n if (layerObj.getElement(elementPath)) {\n throw new CLIError(\n `Element ${elementPath} already exists in ${layer} layer`,\n ErrorCategory.USER,\n [\n `Use \"dr show ${elementPath}\" to view the existing element`,\n `Use \"dr update ${elementPath}\" to modify it`,\n `Use \"dr delete ${elementPath}\" to remove it first if you want to recreate it`,\n ],\n { operation: \"add\", context: `Duplicate element path` }\n );\n }\n\n // Unified mutation handler for add operation\n const handler = new MutationHandler(model, elementPath, layer);\n\n // Execute add through unified path (handles staging and base model consistently)\n await handler.executeAdd(element, (elem) => {\n // This mutator is called by executeAdd for base model path only\n layerObj.addElement(elem);\n });\n\n // Determine if operation was staged or applied to base model\n if (handler.getAfterState()) {\n // Check if we went through staging path\n const stagingManager = handler.getStagingManager();\n const activeChangeset = await stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path\n handleSuccess(\n `Staged element ${ansis.bold(elementPath)} to ${ansis.bold(activeChangeset.name)}`,\n {\n elementId: elementPath,\n layer,\n type: resolvedType,\n name: options.name || name,\n changesetStatus: \"staged\",\n changeset: activeChangeset.name,\n },\n { verbose: options.verbose }\n );\n } else {\n // Base model path\n handleSuccess(`Added element ${ansis.bold(elementPath)} to ${ansis.bold(layer)} layer`, {\n elementId: elementPath,\n layer,\n type: resolvedType,\n name: options.name || name,\n description: options.description || \"(none)\",\n }, { verbose: true });\n }\n }\n } catch (error) {\n handleError(error);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -9,6 +9,7 @@ import { CLIError, ModelNotFoundError, ErrorCategory, categorizeError } from "..
|
|
|
9
9
|
import { findProjectRoot } from "../utils/project-paths.js";
|
|
10
10
|
import { performDiscover } from "./discover-logic.js";
|
|
11
11
|
import { formatVerifyReport } from "../export/verify-formatters.js";
|
|
12
|
+
import { Model } from "../core/model.js";
|
|
12
13
|
function analyzerCommands(program) {
|
|
13
14
|
const analyzer = program.command("analyzer").description("Manage analyzer discovery and indexing");
|
|
14
15
|
analyzer.command("discover").description("Discover and select an analyzer").option("--json", "Output as JSON").option("--reselect", "Force re-selection even if analyzer already selected").addHelpText("after", `
|
|
@@ -16,12 +17,13 @@ Examples:
|
|
|
16
17
|
$ dr analyzer discover # Scan and select analyzer
|
|
17
18
|
$ dr analyzer discover --reselect # Force re-selection
|
|
18
19
|
$ dr analyzer discover --json # Output discovery results as JSON`).action(async (options) => {
|
|
20
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
19
21
|
try {
|
|
20
22
|
const projectRoot = await findProjectRoot() || process.cwd(), registry = AnalyzerRegistry.getInstance();
|
|
21
23
|
if (await registry.initialize(), !options.reselect) {
|
|
22
24
|
const session = await readSession(projectRoot);
|
|
23
25
|
if (session)
|
|
24
|
-
if (
|
|
26
|
+
if (jsonMode) {
|
|
25
27
|
const analyzerNames = await registry.getAnalyzerNames(), analyzerOptions2 = [];
|
|
26
28
|
for (const name of analyzerNames)
|
|
27
29
|
try {
|
|
@@ -53,11 +55,11 @@ Examples:
|
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
const discoverResult = await performDiscover(registry, {
|
|
56
|
-
json:
|
|
58
|
+
json: jsonMode,
|
|
57
59
|
reselect: options.reselect,
|
|
58
60
|
isTTY: process.stdin.isTTY
|
|
59
61
|
}), { discoveryResult, installed, analyzerOptions, selectedAnalyzer, shouldWriteSession } = discoverResult;
|
|
60
|
-
if (
|
|
62
|
+
if (jsonMode) {
|
|
61
63
|
if (selectedAnalyzer && shouldWriteSession) {
|
|
62
64
|
const state = {
|
|
63
65
|
active_analyzer: selectedAnalyzer,
|
|
@@ -113,6 +115,7 @@ Examples:
|
|
|
113
115
|
$ dr analyzer status # Show status of active analyzer
|
|
114
116
|
$ dr analyzer status --name cbm # Show status of specific analyzer
|
|
115
117
|
$ dr analyzer status --json # Output as JSON`).action(async (options) => {
|
|
118
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
116
119
|
try {
|
|
117
120
|
const projectRoot = await findProjectRoot() || process.cwd();
|
|
118
121
|
let analyzerName = options.name;
|
|
@@ -129,11 +132,16 @@ Examples:
|
|
|
129
132
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND, ["Check the analyzer name with `dr analyzer discover`"]);
|
|
130
133
|
const actualProjectRoot = await findProjectRoot();
|
|
131
134
|
let status;
|
|
132
|
-
if (actualProjectRoot
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
if (actualProjectRoot) {
|
|
136
|
+
const model = await Model.load(actualProjectRoot);
|
|
137
|
+
status = await backend.status(actualProjectRoot, { codebaseRoot: model.codebaseRoot });
|
|
138
|
+
} else
|
|
139
|
+
status = {
|
|
140
|
+
detected: await backend.detect(),
|
|
141
|
+
indexed: !1,
|
|
142
|
+
fresh: !1
|
|
143
|
+
};
|
|
144
|
+
if (jsonMode) {
|
|
137
145
|
console.log(JSON.stringify(status, null, 2)), actualProjectRoot && await writeStatus(status, actualProjectRoot, analyzerName);
|
|
138
146
|
return;
|
|
139
147
|
}
|
|
@@ -172,8 +180,9 @@ Examples:
|
|
|
172
180
|
`Visit: ${homepageUrl}`
|
|
173
181
|
]);
|
|
174
182
|
}
|
|
183
|
+
const model = await Model.load(projectRoot);
|
|
175
184
|
console.log(`Indexing project with ${analyzerName}...`);
|
|
176
|
-
const result = await backend.index(projectRoot, { force: options.force });
|
|
185
|
+
const result = await backend.index(projectRoot, { force: options.force, codebaseRoot: model.codebaseRoot });
|
|
177
186
|
console.log(ansis.green("\u2713 Indexing complete")), console.log(` Nodes: ${result.node_count}`), console.log(` Edges: ${result.edge_count}`), console.log(` Git HEAD: ${result.git_head}`);
|
|
178
187
|
} catch (error) {
|
|
179
188
|
if (error instanceof CLIError || error instanceof ModelNotFoundError)
|
|
@@ -186,6 +195,7 @@ Examples:
|
|
|
186
195
|
$ dr analyzer endpoints # List endpoints from active analyzer
|
|
187
196
|
$ dr analyzer endpoints --json # Output as JSON
|
|
188
197
|
$ dr analyzer endpoints --name cbm # List endpoints from specific analyzer`).action(async (options) => {
|
|
198
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
189
199
|
try {
|
|
190
200
|
const projectRoot = await findProjectRoot();
|
|
191
201
|
if (!projectRoot)
|
|
@@ -202,10 +212,11 @@ Examples:
|
|
|
202
212
|
const backend = await registry.getAnalyzer(analyzerName);
|
|
203
213
|
if (!backend)
|
|
204
214
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
205
|
-
|
|
215
|
+
const model = await Model.load(projectRoot);
|
|
216
|
+
if (!(await backend.status(projectRoot, { codebaseRoot: model.codebaseRoot })).indexed)
|
|
206
217
|
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` to index the project first"]);
|
|
207
|
-
const endpoints = await backend.endpoints(projectRoot);
|
|
208
|
-
if (
|
|
218
|
+
const endpoints = await backend.endpoints(projectRoot, { codebaseRoot: model.codebaseRoot });
|
|
219
|
+
if (jsonMode) {
|
|
209
220
|
console.log(JSON.stringify(endpoints, null, 2));
|
|
210
221
|
return;
|
|
211
222
|
}
|
|
@@ -232,6 +243,7 @@ Examples:
|
|
|
232
243
|
$ dr analyzer services # List all services
|
|
233
244
|
$ dr analyzer services --layer application
|
|
234
245
|
$ dr analyzer services --json # Output as JSON`).action(async (options) => {
|
|
246
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
235
247
|
try {
|
|
236
248
|
const projectRoot = await findProjectRoot();
|
|
237
249
|
if (!projectRoot)
|
|
@@ -248,10 +260,11 @@ Examples:
|
|
|
248
260
|
const backend = await registry.getAnalyzer(analyzerName);
|
|
249
261
|
if (!backend)
|
|
250
262
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
263
|
+
const model = await Model.load(projectRoot);
|
|
251
264
|
if (!await readIndexMeta(projectRoot, analyzerName))
|
|
252
265
|
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
|
|
253
|
-
let services = await backend.services(projectRoot);
|
|
254
|
-
if (options.layer && (services = services.filter((s) => s.suggested_layer === options.layer)),
|
|
266
|
+
let services = await backend.services(projectRoot, { codebaseRoot: model.codebaseRoot });
|
|
267
|
+
if (options.layer && (services = services.filter((s) => s.suggested_layer === options.layer)), jsonMode) {
|
|
255
268
|
console.log(JSON.stringify(services, null, 2));
|
|
256
269
|
return;
|
|
257
270
|
}
|
|
@@ -277,6 +290,7 @@ Examples:
|
|
|
277
290
|
Examples:
|
|
278
291
|
$ dr analyzer datastores # List all inferred datastores
|
|
279
292
|
$ dr analyzer datastores --json # Output as JSON`).action(async (options) => {
|
|
293
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
280
294
|
try {
|
|
281
295
|
const projectRoot = await findProjectRoot();
|
|
282
296
|
if (!projectRoot)
|
|
@@ -293,10 +307,11 @@ Examples:
|
|
|
293
307
|
const backend = await registry.getAnalyzer(analyzerName);
|
|
294
308
|
if (!backend)
|
|
295
309
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
310
|
+
const model = await Model.load(projectRoot);
|
|
296
311
|
if (!await readIndexMeta(projectRoot, analyzerName))
|
|
297
312
|
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
|
|
298
|
-
const datastores = await backend.datastores(projectRoot);
|
|
299
|
-
if (
|
|
313
|
+
const datastores = await backend.datastores(projectRoot, { codebaseRoot: model.codebaseRoot });
|
|
314
|
+
if (jsonMode) {
|
|
300
315
|
console.log(JSON.stringify(datastores, null, 2));
|
|
301
316
|
return;
|
|
302
317
|
}
|
|
@@ -323,6 +338,7 @@ Examples:
|
|
|
323
338
|
$ dr analyzer callers com.example.Service.handleRequest
|
|
324
339
|
$ dr analyzer callers com.example.Service.handleRequest --depth 5
|
|
325
340
|
$ dr analyzer callers com.example.Service.handleRequest --json`).action(async (qualifiedName, options) => {
|
|
341
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
326
342
|
try {
|
|
327
343
|
const depth = parseInt(options.depth, 10);
|
|
328
344
|
if (isNaN(depth) || depth < 1)
|
|
@@ -342,10 +358,11 @@ Examples:
|
|
|
342
358
|
const backend = await registry.getAnalyzer(analyzerName);
|
|
343
359
|
if (!backend)
|
|
344
360
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
361
|
+
const model = await Model.load(projectRoot);
|
|
345
362
|
if (!await readIndexMeta(projectRoot, analyzerName))
|
|
346
363
|
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
|
|
347
|
-
const callers = await backend.callers(projectRoot, qualifiedName, depth);
|
|
348
|
-
if (
|
|
364
|
+
const callers = await backend.callers(projectRoot, qualifiedName, depth, { codebaseRoot: model.codebaseRoot });
|
|
365
|
+
if (jsonMode) {
|
|
349
366
|
console.log(JSON.stringify(callers, null, 2));
|
|
350
367
|
return;
|
|
351
368
|
}
|
|
@@ -368,6 +385,7 @@ Examples:
|
|
|
368
385
|
$ dr analyzer callees com.example.Service.handleRequest
|
|
369
386
|
$ dr analyzer callees com.example.Service.handleRequest --depth 5
|
|
370
387
|
$ dr analyzer callees com.example.Service.handleRequest --json`).action(async (qualifiedName, options) => {
|
|
388
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
371
389
|
try {
|
|
372
390
|
const depth = parseInt(options.depth, 10);
|
|
373
391
|
if (isNaN(depth) || depth < 1)
|
|
@@ -387,10 +405,11 @@ Examples:
|
|
|
387
405
|
const backend = await registry.getAnalyzer(analyzerName);
|
|
388
406
|
if (!backend)
|
|
389
407
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
408
|
+
const model = await Model.load(projectRoot);
|
|
390
409
|
if (!await readIndexMeta(projectRoot, analyzerName))
|
|
391
410
|
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
|
|
392
|
-
const callees = await backend.callees(projectRoot, qualifiedName, depth);
|
|
393
|
-
if (
|
|
411
|
+
const callees = await backend.callees(projectRoot, qualifiedName, depth, { codebaseRoot: model.codebaseRoot });
|
|
412
|
+
if (jsonMode) {
|
|
394
413
|
console.log(JSON.stringify(callees, null, 2));
|
|
395
414
|
return;
|
|
396
415
|
}
|
|
@@ -434,9 +453,10 @@ Examples:
|
|
|
434
453
|
const backend = await registry.getAnalyzer(analyzerName);
|
|
435
454
|
if (!backend)
|
|
436
455
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
456
|
+
const model = await Model.load(projectRoot);
|
|
437
457
|
if (!await readIndexMeta(projectRoot, analyzerName))
|
|
438
458
|
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
|
|
439
|
-
const result = await backend.query(projectRoot, cypher);
|
|
459
|
+
const result = await backend.query(projectRoot, cypher, { codebaseRoot: model.codebaseRoot });
|
|
440
460
|
options.json, console.log(JSON.stringify(result, null, 2));
|
|
441
461
|
} catch (error) {
|
|
442
462
|
if (error instanceof CLIError || error instanceof ModelNotFoundError)
|
|
@@ -452,9 +472,10 @@ Examples:
|
|
|
452
472
|
$ dr analyzer verify --format markdown # Output as Markdown to stdout
|
|
453
473
|
$ dr analyzer verify --output report.json # Save report to file (format inferred as JSON)
|
|
454
474
|
$ dr analyzer verify --output report.md # Save report as Markdown`).action(async (options) => {
|
|
475
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
455
476
|
try {
|
|
456
477
|
let format = "text";
|
|
457
|
-
if (
|
|
478
|
+
if (jsonMode)
|
|
458
479
|
options.format && console.warn(ansis.yellow(`\u26A0 Both --json and --format "${options.format}" were provided. Using --json format (--format is ignored).`)), format = "json";
|
|
459
480
|
else if (options.format) {
|
|
460
481
|
const validFormats = ["text", "json", "markdown"];
|
|
@@ -485,11 +506,13 @@ Examples:
|
|
|
485
506
|
const backend = await registry.getAnalyzer(analyzerName);
|
|
486
507
|
if (!backend)
|
|
487
508
|
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
509
|
+
const model = await Model.load(projectRoot);
|
|
488
510
|
if (!await readIndexMeta(projectRoot, analyzerName))
|
|
489
511
|
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
|
|
490
512
|
const report = await backend.verify(projectRoot, {
|
|
491
513
|
layers: apiLayers,
|
|
492
|
-
changesetAware: !0
|
|
514
|
+
changesetAware: !0,
|
|
515
|
+
codebaseRoot: model.codebaseRoot
|
|
493
516
|
}), formatted = formatVerifyReport(report, { format });
|
|
494
517
|
if (options.output) {
|
|
495
518
|
const outputPath = path.resolve(options.output);
|
|
@@ -503,6 +526,94 @@ Examples:
|
|
|
503
526
|
const cliError = new CLIError(error instanceof Error ? error.message : String(error), categorizeError(error));
|
|
504
527
|
throw error instanceof Error && (cliError.cause = error), cliError;
|
|
505
528
|
}
|
|
529
|
+
}), analyzer.command("classify").description("Classify the indexed project's symbols into model layers and types (Tier 0: rules only)").option("--name <n>", "Analyzer name (defaults to active from session.json)").option("--tier0-only", "Apply only the analyzer's Tier-0 rules: no model calls, no network (required for now)").option("--label <labels>", "Comma-separated analyzer labels to classify (default: Class, Interface, Function, Method, Module, Route and every label a rule names)").option("--file <glob>", "Only symbols in files matching this glob").option("--exclude <regex>", "Also leave out files matching this regular expression (build and vendored paths always are)").option("--limit <n>", "Stop after this many symbols").option("--cards", "Include each symbol's full card (source and graph neighbourhood) in JSON output").option("--output <file>", "Write the JSON report to a file").option("--json", "Output as JSON").addHelpText("after", `
|
|
530
|
+
Tier 0 is the first step of the classification cascade (docs/analyzers/CASCADE_DESIGN.md):
|
|
531
|
+
the analyzer's rules decide a symbol's layer and type, reject it as not a model element,
|
|
532
|
+
or narrow its choices for a later tier. Symbols no rule covers are reported as undecided.
|
|
533
|
+
Nothing is written to the model.
|
|
534
|
+
|
|
535
|
+
Examples:
|
|
536
|
+
$ dr analyzer classify --tier0-only
|
|
537
|
+
$ dr analyzer classify --tier0-only --json > tier0.json
|
|
538
|
+
$ dr analyzer classify --tier0-only --label Class,Method --file "src/main/**"
|
|
539
|
+
$ dr analyzer classify --tier0-only --cards --output tier0-cards.json`).action(async (options) => {
|
|
540
|
+
const jsonMode = options.json ?? program.opts().json;
|
|
541
|
+
try {
|
|
542
|
+
if (!options.tier0Only)
|
|
543
|
+
throw new CLIError("Only Tier-0 classification is available so far: pass --tier0-only", ErrorCategory.USER, ["Model-backed classification (Tier 1) needs the per-project opt-in and is not built yet"]);
|
|
544
|
+
let exclude;
|
|
545
|
+
if (options.exclude !== void 0)
|
|
546
|
+
try {
|
|
547
|
+
exclude = new RegExp(String(options.exclude));
|
|
548
|
+
} catch (e) {
|
|
549
|
+
throw new CLIError(`Invalid --exclude regular expression: ${e instanceof Error ? e.message : String(e)}`, ErrorCategory.USER);
|
|
550
|
+
}
|
|
551
|
+
let limit;
|
|
552
|
+
if (options.limit !== void 0 && (limit = Number(options.limit), !Number.isInteger(limit) || limit < 1))
|
|
553
|
+
throw new CLIError(`--limit must be a positive integer, got '${options.limit}'`, ErrorCategory.USER);
|
|
554
|
+
const labels = options.label ? String(options.label).split(",").map((l) => l.trim()).filter(Boolean) : void 0;
|
|
555
|
+
options.cards && !jsonMode && !options.output && console.error(ansis.yellow("--cards only affects JSON output: add --json or --output <file>"));
|
|
556
|
+
const projectRoot = await findProjectRoot();
|
|
557
|
+
if (!projectRoot)
|
|
558
|
+
throw new ModelNotFoundError();
|
|
559
|
+
let analyzerName = options.name;
|
|
560
|
+
if (!analyzerName) {
|
|
561
|
+
const session = await readSession(projectRoot);
|
|
562
|
+
if (!session)
|
|
563
|
+
throw new CLIError("No analyzer selected. Run `dr analyzer discover` first.", ErrorCategory.USER);
|
|
564
|
+
analyzerName = session.active_analyzer;
|
|
565
|
+
}
|
|
566
|
+
const registry = AnalyzerRegistry.getInstance();
|
|
567
|
+
await registry.initialize();
|
|
568
|
+
const backend = await registry.getAnalyzer(analyzerName);
|
|
569
|
+
if (!backend)
|
|
570
|
+
throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
|
|
571
|
+
if (!backend.classify)
|
|
572
|
+
throw new CLIError(`The ${analyzerName} analyzer does not support classification`, ErrorCategory.USER);
|
|
573
|
+
if (!await readIndexMeta(projectRoot, analyzerName))
|
|
574
|
+
throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
|
|
575
|
+
const model = await Model.load(projectRoot), showProgress = !jsonMode && !options.output && process.stderr.isTTY, report = await backend.classify(projectRoot, {
|
|
576
|
+
codebaseRoot: model.codebaseRoot,
|
|
577
|
+
labels,
|
|
578
|
+
filePattern: options.file,
|
|
579
|
+
exclude,
|
|
580
|
+
limit,
|
|
581
|
+
includeCards: !!options.cards,
|
|
582
|
+
onProgress: showProgress ? (done, total) => {
|
|
583
|
+
(done % 50 === 0 || done === total) && process.stderr.write(`\r ${done}/${total} symbols`), done === total && process.stderr.write(`
|
|
584
|
+
`);
|
|
585
|
+
} : void 0
|
|
586
|
+
});
|
|
587
|
+
if (options.output) {
|
|
588
|
+
const outputPath = path.resolve(options.output);
|
|
589
|
+
await fs.writeFile(outputPath, JSON.stringify(report, null, 2) + `
|
|
590
|
+
`, "utf-8"), jsonMode || console.log(ansis.green(`\u2713 Report written to ${outputPath}`));
|
|
591
|
+
}
|
|
592
|
+
if (jsonMode) {
|
|
593
|
+
console.log(JSON.stringify(report, null, 2));
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
const { summary } = report, pct = (n) => summary.cards ? `${(100 * n / summary.cards).toFixed(0)}%` : "0%";
|
|
597
|
+
console.log(""), console.log(ansis.bold(`Tier-0 classification: ${summary.cards} symbols, ${report.rules} rules`)), console.log(ansis.dim("\u2500".repeat(60))), console.log(` ${ansis.green("decided")} ${String(summary.decided).padStart(6)} ${pct(summary.decided)}`), console.log(` ${ansis.yellow("rejected")} ${String(summary.rejected).padStart(6)} ${pct(summary.rejected)} (not model elements)`), console.log(` ${ansis.cyan("narrowed")} ${String(summary.narrowed).padStart(6)} ${pct(summary.narrowed)} (choices restricted for Tier 1)`), console.log(` ${ansis.dim("undecided")} ${String(summary.undecided).padStart(6)} ${pct(summary.undecided)}`), summary.no_source && console.log(ansis.yellow(` ${summary.no_source} symbol(s) had no source, so rules that read the declaration could not apply`));
|
|
598
|
+
const targets = Object.entries(summary.by_target).sort((a, b) => b[1] - a[1]);
|
|
599
|
+
if (targets.length) {
|
|
600
|
+
console.log(""), console.log(ansis.bold("Decided, by type:"));
|
|
601
|
+
for (const [target, n] of targets)
|
|
602
|
+
console.log(` ${target.padEnd(40)} ${String(n).padStart(6)}`);
|
|
603
|
+
}
|
|
604
|
+
const rules = Object.entries(summary.by_rule).sort((a, b) => b[1] - a[1]);
|
|
605
|
+
if (rules.length) {
|
|
606
|
+
console.log(""), console.log(ansis.bold("Matches, by rule:"));
|
|
607
|
+
for (const [rule, n] of rules)
|
|
608
|
+
console.log(` ${rule.padEnd(40)} ${String(n).padStart(6)}`);
|
|
609
|
+
}
|
|
610
|
+
console.log(ansis.dim("\u2500".repeat(60))), console.log(ansis.dim("Per-symbol outcomes: --json or --output <file>")), console.log("");
|
|
611
|
+
} catch (error) {
|
|
612
|
+
if (error instanceof CLIError || error instanceof ModelNotFoundError)
|
|
613
|
+
throw error;
|
|
614
|
+
const cliError = new CLIError(error instanceof Error ? error.message : String(error), categorizeError(error));
|
|
615
|
+
throw error instanceof Error && (cliError.cause = error), cliError;
|
|
616
|
+
}
|
|
506
617
|
});
|
|
507
618
|
}
|
|
508
619
|
export {
|