@documentation-robotics/cli 0.1.12 → 0.2.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.
Files changed (189) hide show
  1. package/README.md +39 -1
  2. package/dist/analyzers/verify-engine.js +22 -19
  3. package/dist/analyzers/verify-engine.js.map +2 -2
  4. package/dist/cli.js +101 -27
  5. package/dist/cli.js.map +3 -3
  6. package/dist/coding-agents/agents/claude-code.js +3 -1
  7. package/dist/coding-agents/agents/claude-code.js.map +2 -2
  8. package/dist/coding-agents/claude-code-client.js +2 -1
  9. package/dist/coding-agents/claude-code-client.js.map +2 -2
  10. package/dist/coding-agents/copilot-client.js +17 -12
  11. package/dist/coding-agents/copilot-client.js.map +2 -2
  12. package/dist/coding-agents/default-permissions.js +122 -0
  13. package/dist/coding-agents/default-permissions.js.map +7 -0
  14. package/dist/commands/add.js +10 -6
  15. package/dist/commands/add.js.map +2 -2
  16. package/dist/commands/analyzer.js +18 -10
  17. package/dist/commands/analyzer.js.map +2 -2
  18. package/dist/commands/audit.js +6 -6
  19. package/dist/commands/audit.js.map +2 -2
  20. package/dist/commands/changeset.js +238 -145
  21. package/dist/commands/changeset.js.map +2 -2
  22. package/dist/commands/delete.js +45 -18
  23. package/dist/commands/delete.js.map +3 -3
  24. package/dist/commands/element.js +3 -2
  25. package/dist/commands/element.js.map +2 -2
  26. package/dist/commands/farm.js +657 -0
  27. package/dist/commands/farm.js.map +7 -0
  28. package/dist/commands/init.js +11 -1
  29. package/dist/commands/init.js.map +2 -2
  30. package/dist/commands/mcp.js +107 -0
  31. package/dist/commands/mcp.js.map +7 -0
  32. package/dist/commands/relationship.js +53 -30
  33. package/dist/commands/relationship.js.map +2 -2
  34. package/dist/commands/reports.js +1 -1
  35. package/dist/commands/reports.js.map +2 -2
  36. package/dist/commands/update.js +19 -6
  37. package/dist/commands/update.js.map +2 -2
  38. package/dist/commands/validate.js +41 -3
  39. package/dist/commands/validate.js.map +2 -2
  40. package/dist/commands/version.js +2 -2
  41. package/dist/commands/version.js.map +2 -2
  42. package/dist/config.js +83 -0
  43. package/dist/config.js.map +7 -0
  44. package/dist/core/annotation-store.js +138 -0
  45. package/dist/core/annotation-store.js.map +7 -0
  46. package/dist/core/farm-manifest.js +134 -0
  47. package/dist/core/farm-manifest.js.map +7 -0
  48. package/dist/core/farm-sync-engine.js +346 -0
  49. package/dist/core/farm-sync-engine.js.map +7 -0
  50. package/dist/core/farm-sync-state.js +159 -0
  51. package/dist/core/farm-sync-state.js.map +7 -0
  52. package/dist/core/manifest.js +6 -3
  53. package/dist/core/manifest.js.map +2 -2
  54. package/dist/core/migration-registry.js +55 -1
  55. package/dist/core/migration-registry.js.map +2 -2
  56. package/dist/core/model.js +177 -16
  57. package/dist/core/model.js.map +3 -3
  58. package/dist/core/virtual-projection.js +1 -0
  59. package/dist/core/virtual-projection.js.map +2 -2
  60. package/dist/generated/node-types.js +1 -1
  61. package/dist/generated/node-types.js.map +2 -2
  62. package/dist/generated/relationship-index.js +45 -9
  63. package/dist/generated/relationship-index.js.map +2 -2
  64. package/dist/integrations/claude_code/docs/MCP_SERVER.md +55 -0
  65. package/dist/integrations/claude_code/docs/README.md +4 -0
  66. package/dist/mcp/api-key-manager.js +98 -0
  67. package/dist/mcp/api-key-manager.js.map +7 -0
  68. package/dist/mcp/http-transport.js +176 -0
  69. package/dist/mcp/http-transport.js.map +7 -0
  70. package/dist/mcp/resource-registry.js +97 -0
  71. package/dist/mcp/resource-registry.js.map +7 -0
  72. package/dist/mcp/tool-registry.js +44 -0
  73. package/dist/mcp/tool-registry.js.map +7 -0
  74. package/dist/mcp/tools/annotation-create.js +39 -0
  75. package/dist/mcp/tools/annotation-create.js.map +7 -0
  76. package/dist/mcp/tools/annotation-delete.js +29 -0
  77. package/dist/mcp/tools/annotation-delete.js.map +7 -0
  78. package/dist/mcp/tools/annotation-get.js +29 -0
  79. package/dist/mcp/tools/annotation-get.js.map +7 -0
  80. package/dist/mcp/tools/annotation-list.js +24 -0
  81. package/dist/mcp/tools/annotation-list.js.map +7 -0
  82. package/dist/mcp/tools/annotation-reply.js +34 -0
  83. package/dist/mcp/tools/annotation-reply.js.map +7 -0
  84. package/dist/mcp/tools/annotation-shared.js +10 -0
  85. package/dist/mcp/tools/annotation-shared.js.map +7 -0
  86. package/dist/mcp/tools/annotation-update.js +39 -0
  87. package/dist/mcp/tools/annotation-update.js.map +7 -0
  88. package/dist/mcp/tools/changeset-list.js +33 -0
  89. package/dist/mcp/tools/changeset-list.js.map +7 -0
  90. package/dist/mcp/tools/changeset-show.js +39 -0
  91. package/dist/mcp/tools/changeset-show.js.map +7 -0
  92. package/dist/mcp/tools/chat-launch.js +50 -0
  93. package/dist/mcp/tools/chat-launch.js.map +7 -0
  94. package/dist/mcp/tools/chat-status.js +26 -0
  95. package/dist/mcp/tools/chat-status.js.map +7 -0
  96. package/dist/mcp/tools/index.js +47 -0
  97. package/dist/mcp/tools/index.js.map +7 -0
  98. package/dist/mcp/tools/model-add.js +106 -0
  99. package/dist/mcp/tools/model-add.js.map +7 -0
  100. package/dist/mcp/tools/model-delete.js +99 -0
  101. package/dist/mcp/tools/model-delete.js.map +7 -0
  102. package/dist/mcp/tools/model-export.js +72 -0
  103. package/dist/mcp/tools/model-export.js.map +7 -0
  104. package/dist/mcp/tools/model-info.js +51 -0
  105. package/dist/mcp/tools/model-info.js.map +7 -0
  106. package/dist/mcp/tools/model-list.js +53 -0
  107. package/dist/mcp/tools/model-list.js.map +7 -0
  108. package/dist/mcp/tools/model-reload.js +34 -0
  109. package/dist/mcp/tools/model-reload.js.map +7 -0
  110. package/dist/mcp/tools/model-search.js +88 -0
  111. package/dist/mcp/tools/model-search.js.map +7 -0
  112. package/dist/mcp/tools/model-show.js +41 -0
  113. package/dist/mcp/tools/model-show.js.map +7 -0
  114. package/dist/mcp/tools/model-stats.js +22 -0
  115. package/dist/mcp/tools/model-stats.js.map +7 -0
  116. package/dist/mcp/tools/model-trace.js +55 -0
  117. package/dist/mcp/tools/model-trace.js.map +7 -0
  118. package/dist/mcp/tools/model-update.js +105 -0
  119. package/dist/mcp/tools/model-update.js.map +7 -0
  120. package/dist/mcp/tools/model-validate.js +78 -0
  121. package/dist/mcp/tools/model-validate.js.map +7 -0
  122. package/dist/mcp/tools/shared.js +103 -0
  123. package/dist/mcp/tools/shared.js.map +7 -0
  124. package/dist/reports/model-layer-report-generator.js +5 -3
  125. package/dist/reports/model-layer-report-generator.js.map +2 -2
  126. package/dist/reports/model-readme-generator.js +116 -0
  127. package/dist/reports/model-readme-generator.js.map +7 -0
  128. package/dist/reports/model-report-data.js +37 -1
  129. package/dist/reports/model-report-data.js.map +2 -2
  130. package/dist/reports/model-report-orchestrator.js +29 -6
  131. package/dist/reports/model-report-orchestrator.js.map +2 -2
  132. package/dist/reports/model-report-utils.js +9 -0
  133. package/dist/reports/model-report-utils.js.map +7 -0
  134. package/dist/schemas/bundled/analyzers/cbm.json +2 -2
  135. package/dist/schemas/bundled/analyzers/manifest.json +2 -2
  136. package/dist/schemas/bundled/api.json +1 -1
  137. package/dist/schemas/bundled/apm.json +1 -1
  138. package/dist/schemas/bundled/application.json +12 -1
  139. package/dist/schemas/bundled/base.json +1 -1
  140. package/dist/schemas/bundled/business.json +1 -1
  141. package/dist/schemas/bundled/data-model.json +38 -2
  142. package/dist/schemas/bundled/data-store.json +1 -1
  143. package/dist/schemas/bundled/manifest.json +4 -4
  144. package/dist/schemas/bundled/motivation.json +1 -1
  145. package/dist/schemas/bundled/navigation.json +1 -1
  146. package/dist/schemas/bundled/product.json +1 -1
  147. package/dist/schemas/bundled/security.json +1 -1
  148. package/dist/schemas/bundled/technology.json +1 -1
  149. package/dist/schemas/bundled/testing.json +1 -1
  150. package/dist/schemas/bundled/ux.json +1 -1
  151. package/dist/server/server.js +45 -7
  152. package/dist/server/server.js.map +2 -2
  153. package/dist/telemetry/config.js +2 -40
  154. package/dist/telemetry/config.js.map +2 -2
  155. package/dist/telemetry/index.js +1 -1
  156. package/dist/types/index.js.map +2 -2
  157. package/dist/utils/ansi-suppressor.js +25 -0
  158. package/dist/utils/ansi-suppressor.js.map +7 -0
  159. package/dist/utils/color-utils.js +34 -0
  160. package/dist/utils/color-utils.js.map +7 -0
  161. package/dist/utils/element-reference-shape.js +15 -1
  162. package/dist/utils/element-reference-shape.js.map +3 -3
  163. package/dist/utils/errors.js +69 -10
  164. package/dist/utils/errors.js.map +2 -2
  165. package/dist/utils/globals.js +17 -1
  166. package/dist/utils/globals.js.map +2 -2
  167. package/dist/utils/project-paths.js +24 -2
  168. package/dist/utils/project-paths.js.map +2 -2
  169. package/dist/utils/reference-path-parser.js +49 -0
  170. package/dist/utils/reference-path-parser.js.map +7 -0
  171. package/dist/utils/source-reference.js +5 -0
  172. package/dist/utils/source-reference.js.map +2 -2
  173. package/dist/utils/spec-version.js +10 -2
  174. package/dist/utils/spec-version.js.map +2 -2
  175. package/dist/validators/composed-reference-validator.js +262 -0
  176. package/dist/validators/composed-reference-validator.js.map +7 -0
  177. package/dist/validators/reference-validator.js +59 -8
  178. package/dist/validators/reference-validator.js.map +3 -3
  179. package/dist/validators/relationship-schema-validator.js +30 -2
  180. package/dist/validators/relationship-schema-validator.js.map +3 -3
  181. package/dist/viewer/README.md +6 -6
  182. package/dist/viewer/assets/main-B7AOQXXX.js +81 -0
  183. package/dist/viewer/assets/main-vdrFrG7q.css +1 -0
  184. package/dist/viewer/index.html +2 -2
  185. package/dist/viewer/manifest.json +10 -10
  186. package/dist/viewer/version.json +1 -1
  187. package/package.json +6 -3
  188. package/dist/viewer/assets/main-BRPZyc36.css +0 -1
  189. package/dist/viewer/assets/main-BrpLargo.js +0 -81
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/commands/analyzer.ts"],
4
- "sourcesContent": ["/**\n * Analyzer Commands - CLI surface for analyzer discovery, status, indexing, and querying\n *\n * Implements ten subcommands:\n * - discover: Scan for installed analyzers and select active analyzer\n * - status: Report analyzer detection and project index state\n * - index: Index the current project with the active analyzer\n * - endpoints: List discovered API endpoints from indexed project\n * - services: Query for services/components in the indexed project\n * - datastores: Query for datastores/databases inferred from code analysis\n * - callers: Query for callers of a specific function or symbol\n * - callees: Query for callees of a specific function or symbol\n * - query: Execute a raw query against the analyzer's graph\n * - verify: Verify that graph-discovered routes align with model endpoints\n */\n\nimport { Command } from \"commander\";\nimport { intro, outro, select, isCancel } from \"@clack/prompts\";\nimport ansis from \"ansis\";\nimport { promises as fs } from \"fs\";\nimport * as path from \"path\";\nimport { AnalyzerRegistry } from \"../analyzers/registry.js\";\nimport { MappingLoader } from \"../analyzers/mapping-loader.js\";\nimport { readSession, writeSession, writeStatus, readIndexMeta } from \"../analyzers/session-state.js\";\nimport { CLIError, ModelNotFoundError, ErrorCategory, categorizeError } from \"../utils/errors.js\";\nimport { findProjectRoot } from \"../utils/project-paths.js\";\nimport { performDiscover } from \"./discover-logic.js\";\nimport { formatVerifyReport } from \"../export/verify-formatters.js\";\nimport type { SessionState, AnalyzerStatus } from \"../analyzers/types.js\";\n\n/**\n * Register all analyzer subcommands\n */\nexport function analyzerCommands(program: Command): void {\n const analyzer = program.command(\"analyzer\").description(\"Manage analyzer discovery and indexing\");\n\n /**\n * Discover subcommand - scan for installed analyzers\n *\n * Iterates through all registered analyzers, detects which are installed,\n * and prompts for selection if needed. Persists selection to session.json.\n */\n analyzer\n .command(\"discover\")\n .description(\"Discover and select an analyzer\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--reselect\", \"Force re-selection even if analyzer already selected\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer discover # Scan and select analyzer\n $ dr analyzer discover --reselect # Force re-selection\n $ dr analyzer discover --json # Output discovery results as JSON`\n )\n .action(async (options) => {\n try {\n // Resolve project root for consistent session state path\n const projectRoot = (await findProjectRoot()) || process.cwd();\n\n // Initialize registry\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n\n // Check if session already exists and not reselecting\n if (!options.reselect) {\n const session = await readSession(projectRoot);\n if (session) {\n if (options.json) {\n // JSON mode: return discovery results with existing session as selected\n const analyzerNames = await registry.getAnalyzerNames();\n const analyzerOptions: any[] = [];\n\n for (const name of analyzerNames) {\n try {\n const backend = await registry.getAnalyzer(name);\n if (!backend) continue;\n const detection = await backend.detect();\n const mapper = await MappingLoader.load(name);\n const metadata = mapper.getAnalyzerMetadata();\n analyzerOptions.push({ backend, detection, metadata });\n } catch (error) {\n // Log error but continue discovering other analyzers\n const errorMsg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to discover analyzer \"${name}\": ${errorMsg}`);\n }\n }\n\n const installed = analyzerOptions.filter((a) => a.detection.installed);\n const discoveryResult: any = {\n found: analyzerOptions.map((a) => ({\n name: a.backend.name,\n display_name: a.backend.displayName,\n description: a.metadata?.description || \"\",\n homepage: a.metadata?.homepage || \"\",\n installed: a.detection.installed,\n })),\n installed_count: installed.length,\n selected: session.active_analyzer,\n };\n\n console.log(JSON.stringify(discoveryResult, null, 2));\n return;\n } else {\n // Text mode: show message and return\n console.log(\n ansis.green(`\u2713 Using analyzer: ${session.active_analyzer} (use --reselect to change)`)\n );\n return;\n }\n }\n }\n\n // Run core discover logic\n const discoverResult = await performDiscover(registry, {\n json: options.json,\n reselect: options.reselect,\n isTTY: process.stdin.isTTY,\n });\n\n const { discoveryResult, installed, analyzerOptions, selectedAnalyzer, shouldWriteSession } = discoverResult;\n\n // JSON output mode\n if (options.json) {\n // Only write session if an analyzer was actually selected\n // (selectedAnalyzer is only set if analyzers are installed)\n if (selectedAnalyzer && shouldWriteSession) {\n const state: SessionState = {\n active_analyzer: selectedAnalyzer,\n selected_at: new Date().toISOString(),\n };\n await writeSession(state, projectRoot);\n discoveryResult.selected = selectedAnalyzer;\n }\n\n console.log(JSON.stringify(discoveryResult, null, 2));\n return;\n }\n\n // Text output mode - show all analyzers with install status\n if (installed.length === 0) {\n intro(ansis.blue(\"\uD83D\uDCCA Analyzer Discovery\"));\n console.log(\"\");\n console.log(ansis.yellow(\"No analyzers installed. Install one of the following:\"));\n console.log(\"\");\n\n for (const opt of analyzerOptions) {\n const name = ansis.bold(opt.backend.displayName);\n const homepage = opt.metadata?.homepage || \"(homepage not available)\";\n console.log(` ${name} ${ansis.dim(`(${homepage})`)}`);\n }\n\n console.log(\"\");\n outro(ansis.dim(\"To install: follow the links above or use your package manager\"));\n\n return;\n }\n\n // Prompt for selection\n intro(ansis.blue(\"\uD83D\uDCCA Analyzer Selection\"));\n\n if (process.stdin.isTTY) {\n const selectedName = await select({\n message: \"Select an analyzer\",\n options: installed.map((a) => ({\n value: a.backend.name,\n label: a.backend.displayName,\n hint: a.metadata?.description || \"\",\n })),\n });\n\n if (isCancel(selectedName)) {\n outro(ansis.dim(\"Cancelled\"));\n return;\n }\n\n // Write session\n const state: SessionState = {\n active_analyzer: selectedName as string,\n selected_at: new Date().toISOString(),\n };\n await writeSession(state, projectRoot);\n\n outro(\n ansis.green(\n `\u2713 Selected analyzer: ${selectedName} (saved to .dr/analyzers/session.json)`\n )\n );\n } else {\n // Non-TTY: auto-select first installed analyzer\n if (selectedAnalyzer) {\n const state: SessionState = {\n active_analyzer: selectedAnalyzer,\n selected_at: new Date().toISOString(),\n };\n await writeSession(state, projectRoot);\n\n console.log(\n ansis.green(`\u2713 Selected analyzer: ${selectedAnalyzer} (non-interactive mode)`)\n );\n outro(ansis.dim(\"Saved to .dr/analyzers/session.json\"));\n }\n }\n } catch (error) {\n if (error instanceof CLIError) throw error;\n\n const category = categorizeError(error);\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n category\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Status subcommand - report analyzer detection and project index state\n */\n analyzer\n .command(\"status\")\n .description(\"Check analyzer detection and project index status\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer status # Show status of active analyzer\n $ dr analyzer status --name cbm # Show status of specific analyzer\n $ dr analyzer status --json # Output as JSON`\n )\n .action(async (options) => {\n try {\n // Resolve project root for consistent session state path\n const projectRoot = (await findProjectRoot()) || process.cwd();\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND,\n [\"Check the analyzer name with `dr analyzer discover`\"]\n );\n }\n\n // Get status (use project root from findProjectRoot for backend operations)\n const actualProjectRoot = await findProjectRoot();\n let status: AnalyzerStatus;\n if (actualProjectRoot) {\n status = await backend.status(actualProjectRoot);\n } else {\n const detected = await backend.detect();\n status = {\n detected,\n indexed: false,\n fresh: false,\n } as AnalyzerStatus;\n }\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify(status, null, 2));\n if (actualProjectRoot) {\n await writeStatus(status, actualProjectRoot, analyzerName);\n }\n return;\n }\n\n // Text output\n console.log(\"\");\n console.log(ansis.bold(\"Analyzer Status\"));\n console.log(ansis.dim(\"\u2500\".repeat(40)));\n\n console.log(\n `Installed: ${status.detected.installed ? ansis.green(\"\u2713 Yes\") : ansis.red(\"\u2717 No\")}`\n );\n\n if (status.detected.binary_path) {\n console.log(`Binary: ${ansis.dim(status.detected.binary_path)}`);\n }\n\n if (status.detected.version) {\n console.log(`Version: ${ansis.dim(status.detected.version)}`);\n }\n\n // Only show MCP and contract info if analyzer is installed\n if (status.detected.installed) {\n console.log(\n `MCP Registered: ${status.detected.mcp_registered ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No\")}`\n );\n\n console.log(\n `Contract Valid: ${status.detected.contract_ok ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No\")}`\n );\n }\n\n if (actualProjectRoot) {\n console.log(\n `Indexed: ${status.indexed ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No\")}`\n );\n\n if (status.indexed) {\n console.log(\n `Fresh: ${status.fresh ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No (use --force to reindex)\")}`\n );\n\n if (status.last_indexed) {\n console.log(`Last indexed: ${ansis.dim(status.last_indexed)}`);\n }\n } else {\n console.log(ansis.dim(\"Run `dr analyzer index` to index the project\"));\n }\n }\n\n console.log(\"\");\n\n // Write status file\n if (actualProjectRoot) {\n await writeStatus(status, actualProjectRoot, analyzerName);\n }\n } catch (error) {\n if (error instanceof CLIError) throw error;\n\n const category = categorizeError(error);\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n category\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Index subcommand - index the current project\n */\n analyzer\n .command(\"index\")\n .description(\"Index the current project with the analyzer\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--force\", \"Force re-indexing even if index is fresh\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer index # Index with active analyzer\n $ dr analyzer index --force # Force re-index\n $ dr analyzer index --name cbm # Index with specific analyzer`\n )\n .action(async (options) => {\n try {\n // Find project root - required for indexing\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND,\n [\"Check the analyzer name with `dr analyzer discover`\"]\n );\n }\n\n // Check if installed\n const detection = await backend.detect();\n if (!detection.installed) {\n // Get analyzer metadata for suggestions\n const mapper = await MappingLoader.load(analyzerName);\n const metadata = mapper.getAnalyzerMetadata();\n const homepageUrl = metadata?.homepage || \"https://github.com/search?q=codebase-memory\";\n\n throw new CLIError(\n `Analyzer not installed: ${analyzerName}`,\n ErrorCategory.USER,\n [\n \"Run `dr analyzer discover` to find available analyzers and installation instructions\",\n `Visit: ${homepageUrl}`,\n ]\n );\n }\n\n // Index the project\n console.log(`Indexing project with ${analyzerName}...`);\n const result = await backend.index(projectRoot, { force: options.force });\n\n console.log(ansis.green(`\u2713 Indexing complete`));\n console.log(` Nodes: ${result.node_count}`);\n console.log(` Edges: ${result.edge_count}`);\n console.log(` Git HEAD: ${result.git_head}`);\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n ErrorCategory.SYSTEM\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Endpoints subcommand - list API endpoints from indexed project\n */\n analyzer\n .command(\"endpoints\")\n .description(\"List discovered API endpoints from indexed project\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer endpoints # List endpoints from active analyzer\n $ dr analyzer endpoints --json # Output as JSON\n $ dr analyzer endpoints --name cbm # List endpoints from specific analyzer`\n )\n .action(async (options) => {\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const status = await backend.status(projectRoot);\n if (!status.indexed) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` to index the project first\"]\n );\n }\n\n // Query for endpoints\n const endpoints = await backend.endpoints(projectRoot);\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify(endpoints, null, 2));\n return;\n }\n\n // Table output\n if (endpoints.length === 0) {\n console.log(ansis.yellow(\"No endpoints found\"));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`API Endpoints (${endpoints.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(135)));\n\n // Print header\n const methodWidth = 8;\n const pathWidth = 20;\n const nameWidth = 18;\n const idFragmentWidth = 18;\n const symbolWidth = 18;\n const confidenceWidth = 12;\n const fileWidth = 25;\n\n console.log(\n ansis.cyan(\n `${\"Method\".padEnd(methodWidth)} ${\"Path\".padEnd(pathWidth)} ${\"Name\".padEnd(nameWidth)} ${\"ID Fragment\".padEnd(idFragmentWidth)} ${\"Symbol\".padEnd(symbolWidth)} ${\"Confidence\".padEnd(confidenceWidth)} File`\n )\n );\n console.log(ansis.dim(\"\u2500\".repeat(135)));\n\n // Print each endpoint\n for (const endpoint of endpoints) {\n const method = endpoint.http_method.padEnd(methodWidth);\n const path = endpoint.http_path.substring(0, pathWidth).padEnd(pathWidth);\n const name = endpoint.suggested_name.substring(0, nameWidth).padEnd(nameWidth);\n const idFragment = endpoint.suggested_id_fragment.substring(0, idFragmentWidth).padEnd(idFragmentWidth);\n const symbol = endpoint.source_symbol.substring(0, symbolWidth).padEnd(symbolWidth);\n const confidence = endpoint.confidence.toUpperCase().padEnd(confidenceWidth);\n const file = endpoint.source_file.substring(0, fileWidth);\n\n console.log(`${method} ${path} ${name} ${idFragment} ${symbol} ${confidence} ${ansis.dim(file)}`);\n }\n\n console.log(ansis.dim(\"\u2500\".repeat(135)));\n console.log(ansis.dim(`Total: ${endpoints.length} endpoint(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Services subcommand - query for services/components in indexed project\n */\n analyzer\n .command(\"services\")\n .description(\"Query for services/components in the indexed project\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--layer <layer>\", \"Filter by layer (e.g., 'application')\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer services # List all services\n $ dr analyzer services --layer application\n $ dr analyzer services --json # Output as JSON`\n )\n .action(async (options) => {\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for services\n let services = await backend.services(projectRoot);\n\n // Filter by layer if specified\n if (options.layer) {\n services = services.filter(s => s.suggested_layer === options.layer);\n }\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify(services, null, 2));\n return;\n }\n\n // Table output\n if (services.length === 0) {\n console.log(ansis.yellow(\"No services found\"));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Services (${services.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(120)));\n\n // Print header\n const nameWidth = 20;\n const layerWidth = 15;\n const typeWidth = 18;\n const symbolWidth = 20;\n const confidenceWidth = 12;\n const fileWidth = 25;\n\n console.log(\n ansis.cyan(\n `${\"Name\".padEnd(nameWidth)} ${\"Layer\".padEnd(layerWidth)} ${\"Type\".padEnd(typeWidth)} ${\"Symbol\".padEnd(symbolWidth)} ${\"Confidence\".padEnd(confidenceWidth)} File`\n )\n );\n console.log(ansis.dim(\"\u2500\".repeat(120)));\n\n // Print each service\n for (const service of services) {\n const name = service.suggested_name.substring(0, nameWidth).padEnd(nameWidth);\n const layer = service.suggested_layer.substring(0, layerWidth).padEnd(layerWidth);\n const type = service.suggested_element_type.substring(0, typeWidth).padEnd(typeWidth);\n const symbol = service.source_symbol.substring(0, symbolWidth).padEnd(symbolWidth);\n const confidence = service.confidence.toUpperCase().padEnd(confidenceWidth);\n const file = service.source_file.substring(0, fileWidth);\n\n console.log(`${name} ${layer} ${type} ${symbol} ${confidence} ${ansis.dim(file)}`);\n }\n\n console.log(ansis.dim(\"\u2500\".repeat(120)));\n console.log(ansis.dim(`Total: ${services.length} service(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Datastores subcommand - query for datastores/databases inferred from code\n */\n analyzer\n .command(\"datastores\")\n .description(\"Query for datastores/databases inferred from code analysis\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer datastores # List all inferred datastores\n $ dr analyzer datastores --json # Output as JSON`\n )\n .action(async (options) => {\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for datastores\n const datastores = await backend.datastores(projectRoot);\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify(datastores, null, 2));\n return;\n }\n\n // Table output\n if (datastores.length === 0) {\n console.log(ansis.yellow(\"No datastores found\"));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Datastores (${datastores.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(100)));\n\n // Print each datastore\n for (const ds of datastores) {\n console.log(` ${ansis.cyan(ds.suggested_name)}`);\n console.log(` Inferred from:`);\n for (const evidence of ds.inferred_from) {\n console.log(` - ${evidence.source_file}: ${evidence.import_pattern}`);\n }\n if (ds.notes) {\n console.log(` Notes: ${ds.notes}`);\n }\n console.log(\"\");\n }\n\n console.log(ansis.dim(`Total: ${datastores.length} datastore(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Callers subcommand - query for callers of a specific symbol\n */\n analyzer\n .command(\"callers <qualified-name>\")\n .description(\"Query for callers of a specific function or symbol\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--depth <n>\", \"Maximum depth for call graph traversal (default: 3, max: 10)\", \"3\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer callers com.example.Service.handleRequest\n $ dr analyzer callers com.example.Service.handleRequest --depth 5\n $ dr analyzer callers com.example.Service.handleRequest --json`\n )\n .action(async (qualifiedName, options) => {\n try {\n // Validate depth\n const depth = parseInt(options.depth, 10);\n if (isNaN(depth) || depth < 1) {\n throw new CLIError(\n \"Invalid --depth value: must be a positive integer\",\n ErrorCategory.USER\n );\n }\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for callers\n const callers = await backend.callers(projectRoot, qualifiedName, depth);\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify(callers, null, 2));\n return;\n }\n\n // Table output\n if (callers.length === 0) {\n console.log(ansis.yellow(`No callers found for ${qualifiedName}`));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Callers of ${ansis.cyan(qualifiedName)} (${callers.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(100)));\n\n // Print each caller\n for (const caller of callers) {\n console.log(` ${ansis.bold(caller.qualified_name)}`);\n console.log(` File: ${caller.source_file}`);\n console.log(` Symbol: ${caller.source_symbol}`);\n console.log(` Depth: ${caller.depth}`);\n console.log(` Edge: ${caller.edge_type}`);\n console.log(\"\");\n }\n\n console.log(ansis.dim(`Total: ${callers.length} caller(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Callees subcommand - query for callees of a specific symbol\n */\n analyzer\n .command(\"callees <qualified-name>\")\n .description(\"Query for callees of a specific function or symbol\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--depth <n>\", \"Maximum depth for call graph traversal (default: 3, max: 10)\", \"3\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer callees com.example.Service.handleRequest\n $ dr analyzer callees com.example.Service.handleRequest --depth 5\n $ dr analyzer callees com.example.Service.handleRequest --json`\n )\n .action(async (qualifiedName, options) => {\n try {\n // Validate depth\n const depth = parseInt(options.depth, 10);\n if (isNaN(depth) || depth < 1) {\n throw new CLIError(\n \"Invalid --depth value: must be a positive integer\",\n ErrorCategory.USER\n );\n }\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for callees\n const callees = await backend.callees(projectRoot, qualifiedName, depth);\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify(callees, null, 2));\n return;\n }\n\n // Table output\n if (callees.length === 0) {\n console.log(ansis.yellow(`No callees found for ${qualifiedName}`));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Callees of ${ansis.cyan(qualifiedName)} (${callees.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(100)));\n\n // Print each callee\n for (const callee of callees) {\n console.log(` ${ansis.bold(callee.qualified_name)}`);\n console.log(` File: ${callee.source_file}`);\n console.log(` Symbol: ${callee.source_symbol}`);\n console.log(` Depth: ${callee.depth}`);\n console.log(` Edge: ${callee.edge_type}`);\n console.log(\"\");\n }\n\n console.log(ansis.dim(`Total: ${callees.length} callee(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Query subcommand - execute a raw query against the analyzer's graph\n * Documented as an advanced escape hatch for graph queries (not recommended for scripting)\n */\n analyzer\n .command(\"query <cypher>\")\n .description(\"Execute a raw Cypher query against the analyzer graph (advanced escape hatch)\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON (default format for query results)\")\n .addHelpText(\n \"before\",\n `Advanced Escape Hatch: This command directly executes graph queries without validation or wrapping.\nUse for advanced analysis when standard commands don't meet your needs.\\n`\n )\n .addHelpText(\n \"after\",\n `\nQuery syntax depends on the analyzer backend (e.g., Cypher for graph analyzers).\nResults are always output as JSON.\n\nExamples:\n $ dr analyzer query \"MATCH (n) RETURN n LIMIT 10\"\n $ dr analyzer query \"MATCH (n:Service) RETURN n.name\"\n $ dr analyzer query \"MATCH (n) RETURN n LIMIT 10\" --json`\n )\n .action(async (cypher, options) => {\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Execute query\n const result = await backend.query(projectRoot, cypher);\n\n // Output format: JSON is the only reasonable format for arbitrary query results\n // The --json flag is accepted for consistency, but JSON is always the output format\n // (the flag currently has no effect as all query output is JSON)\n if (options.json === false) {\n // Explicit no-op: --json flag or its absence doesn't change behavior\n // Query results are always output as JSON regardless of flag\n }\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Verify subcommand - verify that graph-discovered routes align with model endpoints\n */\n analyzer\n .command(\"verify\")\n .description(\"Verify that graph-discovered routes align with model endpoints\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--layer <layer>\", \"Layer(s) to verify (can be used multiple times)\", (value, previous: string[] | undefined) => {\n return previous ? [...previous, value] : [value];\n })\n .option(\"--json\", \"Output as JSON\")\n .option(\"--format <format>\", \"Output format: text, json, markdown (default: text)\")\n .option(\"--output <path>\", \"Write report to file\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer verify # Verify api layer (default)\n $ dr analyzer verify --layer api # Explicitly specify api layer\n $ dr analyzer verify --json # Output as JSON to stdout\n $ dr analyzer verify --format markdown # Output as Markdown to stdout\n $ dr analyzer verify --output report.json # Save report to file (format inferred as JSON)\n $ dr analyzer verify --output report.md # Save report as Markdown`\n )\n .action(async (options) => {\n try {\n // Determine output format from --json flag, --format flag, or --output file extension\n let format: \"text\" | \"json\" | \"markdown\" = \"text\";\n if (options.json) {\n // Warn if both --json and --format are provided\n if (options.format) {\n console.warn(ansis.yellow(`\u26A0 Both --json and --format \"${options.format}\" were provided. Using --json format (--format is ignored).`));\n }\n format = \"json\";\n } else if (options.format) {\n const validFormats = [\"text\", \"json\", \"markdown\"];\n if (!validFormats.includes(options.format)) {\n throw new CLIError(\n `Invalid format: \"${options.format}\". Valid values are: ${validFormats.join(\", \")}.`,\n ErrorCategory.USER\n );\n }\n format = options.format as \"text\" | \"json\" | \"markdown\";\n } else if (options.output) {\n const ext = path.extname(options.output).toLowerCase();\n if (ext === \".json\") {\n format = \"json\";\n } else if (ext === \".md\") {\n format = \"markdown\";\n } else if (ext) {\n // Warn if file has unrecognized extension\n console.warn(ansis.yellow(`\u26A0 Unrecognized file extension \"${ext}\" in --output. Using text format by default.`));\n }\n }\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Validate layers - only api is supported in v1\n const requestedLayers = options.layer || [\"api\"];\n const apiLayers = requestedLayers.filter((layer: string) => layer === \"api\");\n const nonApiLayers = requestedLayers.filter((layer: string) => layer !== \"api\");\n\n // Report non-api layers as not available\n for (const layer of nonApiLayers) {\n console.log(ansis.dim(`No verification available for layer '${layer}'`));\n }\n\n // If no api layers to verify, exit cleanly\n if (apiLayers.length === 0) {\n return;\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Execute verification with changeset awareness enabled by default\n const report = await backend.verify(projectRoot, {\n layers: apiLayers,\n changesetAware: true,\n });\n\n const formatted = formatVerifyReport(report, { format });\n\n // Write to file if --output specified\n if (options.output) {\n const outputPath = path.resolve(options.output);\n await fs.writeFile(outputPath, formatted, \"utf-8\");\n console.log(ansis.green(`\u2713 Report written to ${outputPath}`));\n return;\n }\n\n // Print to stdout\n console.log(formatted);\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Analyzer Commands - CLI surface for analyzer discovery, status, indexing, and querying\n *\n * Implements ten subcommands:\n * - discover: Scan for installed analyzers and select active analyzer\n * - status: Report analyzer detection and project index state\n * - index: Index the current project with the active analyzer\n * - endpoints: List discovered API endpoints from indexed project\n * - services: Query for services/components in the indexed project\n * - datastores: Query for datastores/databases inferred from code analysis\n * - callers: Query for callers of a specific function or symbol\n * - callees: Query for callees of a specific function or symbol\n * - query: Execute a raw query against the analyzer's graph\n * - verify: Verify that graph-discovered routes align with model endpoints\n */\n\nimport { Command } from \"commander\";\nimport { intro, outro, select, isCancel } from \"@clack/prompts\";\nimport ansis from \"ansis\";\nimport { promises as fs } from \"fs\";\nimport * as path from \"path\";\nimport { AnalyzerRegistry } from \"../analyzers/registry.js\";\nimport { MappingLoader } from \"../analyzers/mapping-loader.js\";\nimport { readSession, writeSession, writeStatus, readIndexMeta } from \"../analyzers/session-state.js\";\nimport { CLIError, ModelNotFoundError, ErrorCategory, categorizeError } from \"../utils/errors.js\";\nimport { findProjectRoot } from \"../utils/project-paths.js\";\nimport { performDiscover } from \"./discover-logic.js\";\nimport { formatVerifyReport } from \"../export/verify-formatters.js\";\nimport type { SessionState, AnalyzerStatus } from \"../analyzers/types.js\";\n\n/**\n * Register all analyzer subcommands\n */\nexport function analyzerCommands(program: Command): void {\n const analyzer = program.command(\"analyzer\").description(\"Manage analyzer discovery and indexing\");\n\n /**\n * Discover subcommand - scan for installed analyzers\n *\n * Iterates through all registered analyzers, detects which are installed,\n * and prompts for selection if needed. Persists selection to session.json.\n */\n analyzer\n .command(\"discover\")\n .description(\"Discover and select an analyzer\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--reselect\", \"Force re-selection even if analyzer already selected\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer discover # Scan and select analyzer\n $ dr analyzer discover --reselect # Force re-selection\n $ dr analyzer discover --json # Output discovery results as JSON`\n )\n .action(async (options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Resolve project root for consistent session state path\n const projectRoot = (await findProjectRoot()) || process.cwd();\n\n // Initialize registry\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n\n // Check if session already exists and not reselecting\n if (!options.reselect) {\n const session = await readSession(projectRoot);\n if (session) {\n if (jsonMode) {\n // JSON mode: return discovery results with existing session as selected\n const analyzerNames = await registry.getAnalyzerNames();\n const analyzerOptions: any[] = [];\n\n for (const name of analyzerNames) {\n try {\n const backend = await registry.getAnalyzer(name);\n if (!backend) continue;\n const detection = await backend.detect();\n const mapper = await MappingLoader.load(name);\n const metadata = mapper.getAnalyzerMetadata();\n analyzerOptions.push({ backend, detection, metadata });\n } catch (error) {\n // Log error but continue discovering other analyzers\n const errorMsg = error instanceof Error ? error.message : String(error);\n console.error(`Failed to discover analyzer \"${name}\": ${errorMsg}`);\n }\n }\n\n const installed = analyzerOptions.filter((a) => a.detection.installed);\n const discoveryResult: any = {\n found: analyzerOptions.map((a) => ({\n name: a.backend.name,\n display_name: a.backend.displayName,\n description: a.metadata?.description || \"\",\n homepage: a.metadata?.homepage || \"\",\n installed: a.detection.installed,\n })),\n installed_count: installed.length,\n selected: session.active_analyzer,\n };\n\n console.log(JSON.stringify(discoveryResult, null, 2));\n return;\n } else {\n // Text mode: show message and return\n console.log(\n ansis.green(`\u2713 Using analyzer: ${session.active_analyzer} (use --reselect to change)`)\n );\n return;\n }\n }\n }\n\n // Run core discover logic\n const discoverResult = await performDiscover(registry, {\n json: jsonMode,\n reselect: options.reselect,\n isTTY: process.stdin.isTTY,\n });\n\n const { discoveryResult, installed, analyzerOptions, selectedAnalyzer, shouldWriteSession } = discoverResult;\n\n // JSON output mode\n if (jsonMode) {\n // Only write session if an analyzer was actually selected\n // (selectedAnalyzer is only set if analyzers are installed)\n if (selectedAnalyzer && shouldWriteSession) {\n const state: SessionState = {\n active_analyzer: selectedAnalyzer,\n selected_at: new Date().toISOString(),\n };\n await writeSession(state, projectRoot);\n discoveryResult.selected = selectedAnalyzer;\n }\n\n console.log(JSON.stringify(discoveryResult, null, 2));\n return;\n }\n\n // Text output mode - show all analyzers with install status\n if (installed.length === 0) {\n intro(ansis.blue(\"\uD83D\uDCCA Analyzer Discovery\"));\n console.log(\"\");\n console.log(ansis.yellow(\"No analyzers installed. Install one of the following:\"));\n console.log(\"\");\n\n for (const opt of analyzerOptions) {\n const name = ansis.bold(opt.backend.displayName);\n const homepage = opt.metadata?.homepage || \"(homepage not available)\";\n console.log(` ${name} ${ansis.dim(`(${homepage})`)}`);\n }\n\n console.log(\"\");\n outro(ansis.dim(\"To install: follow the links above or use your package manager\"));\n\n return;\n }\n\n // Prompt for selection\n intro(ansis.blue(\"\uD83D\uDCCA Analyzer Selection\"));\n\n if (process.stdin.isTTY) {\n const selectedName = await select({\n message: \"Select an analyzer\",\n options: installed.map((a) => ({\n value: a.backend.name,\n label: a.backend.displayName,\n hint: a.metadata?.description || \"\",\n })),\n });\n\n if (isCancel(selectedName)) {\n outro(ansis.dim(\"Cancelled\"));\n return;\n }\n\n // Write session\n const state: SessionState = {\n active_analyzer: selectedName as string,\n selected_at: new Date().toISOString(),\n };\n await writeSession(state, projectRoot);\n\n outro(\n ansis.green(\n `\u2713 Selected analyzer: ${selectedName} (saved to .dr/analyzers/session.json)`\n )\n );\n } else {\n // Non-TTY: auto-select first installed analyzer\n if (selectedAnalyzer) {\n const state: SessionState = {\n active_analyzer: selectedAnalyzer,\n selected_at: new Date().toISOString(),\n };\n await writeSession(state, projectRoot);\n\n console.log(\n ansis.green(`\u2713 Selected analyzer: ${selectedAnalyzer} (non-interactive mode)`)\n );\n outro(ansis.dim(\"Saved to .dr/analyzers/session.json\"));\n }\n }\n } catch (error) {\n if (error instanceof CLIError) throw error;\n\n const category = categorizeError(error);\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n category\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Status subcommand - report analyzer detection and project index state\n */\n analyzer\n .command(\"status\")\n .description(\"Check analyzer detection and project index status\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer status # Show status of active analyzer\n $ dr analyzer status --name cbm # Show status of specific analyzer\n $ dr analyzer status --json # Output as JSON`\n )\n .action(async (options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Resolve project root for consistent session state path\n const projectRoot = (await findProjectRoot()) || process.cwd();\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND,\n [\"Check the analyzer name with `dr analyzer discover`\"]\n );\n }\n\n // Get status (use project root from findProjectRoot for backend operations)\n const actualProjectRoot = await findProjectRoot();\n let status: AnalyzerStatus;\n if (actualProjectRoot) {\n status = await backend.status(actualProjectRoot);\n } else {\n const detected = await backend.detect();\n status = {\n detected,\n indexed: false,\n fresh: false,\n } as AnalyzerStatus;\n }\n\n // JSON output\n if (jsonMode) {\n console.log(JSON.stringify(status, null, 2));\n if (actualProjectRoot) {\n await writeStatus(status, actualProjectRoot, analyzerName);\n }\n return;\n }\n\n // Text output\n console.log(\"\");\n console.log(ansis.bold(\"Analyzer Status\"));\n console.log(ansis.dim(\"\u2500\".repeat(40)));\n\n console.log(\n `Installed: ${status.detected.installed ? ansis.green(\"\u2713 Yes\") : ansis.red(\"\u2717 No\")}`\n );\n\n if (status.detected.binary_path) {\n console.log(`Binary: ${ansis.dim(status.detected.binary_path)}`);\n }\n\n if (status.detected.version) {\n console.log(`Version: ${ansis.dim(status.detected.version)}`);\n }\n\n // Only show MCP and contract info if analyzer is installed\n if (status.detected.installed) {\n console.log(\n `MCP Registered: ${status.detected.mcp_registered ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No\")}`\n );\n\n console.log(\n `Contract Valid: ${status.detected.contract_ok ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No\")}`\n );\n }\n\n if (actualProjectRoot) {\n console.log(\n `Indexed: ${status.indexed ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No\")}`\n );\n\n if (status.indexed) {\n console.log(\n `Fresh: ${status.fresh ? ansis.green(\"\u2713 Yes\") : ansis.yellow(\"\u2717 No (use --force to reindex)\")}`\n );\n\n if (status.last_indexed) {\n console.log(`Last indexed: ${ansis.dim(status.last_indexed)}`);\n }\n } else {\n console.log(ansis.dim(\"Run `dr analyzer index` to index the project\"));\n }\n }\n\n console.log(\"\");\n\n // Write status file\n if (actualProjectRoot) {\n await writeStatus(status, actualProjectRoot, analyzerName);\n }\n } catch (error) {\n if (error instanceof CLIError) throw error;\n\n const category = categorizeError(error);\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n category\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Index subcommand - index the current project\n */\n analyzer\n .command(\"index\")\n .description(\"Index the current project with the analyzer\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--force\", \"Force re-indexing even if index is fresh\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer index # Index with active analyzer\n $ dr analyzer index --force # Force re-index\n $ dr analyzer index --name cbm # Index with specific analyzer`\n )\n .action(async (options) => {\n try {\n // Find project root - required for indexing\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND,\n [\"Check the analyzer name with `dr analyzer discover`\"]\n );\n }\n\n // Check if installed\n const detection = await backend.detect();\n if (!detection.installed) {\n // Get analyzer metadata for suggestions\n const mapper = await MappingLoader.load(analyzerName);\n const metadata = mapper.getAnalyzerMetadata();\n const homepageUrl = metadata?.homepage || \"https://github.com/search?q=codebase-memory\";\n\n throw new CLIError(\n `Analyzer not installed: ${analyzerName}`,\n ErrorCategory.USER,\n [\n \"Run `dr analyzer discover` to find available analyzers and installation instructions\",\n `Visit: ${homepageUrl}`,\n ]\n );\n }\n\n // Index the project\n console.log(`Indexing project with ${analyzerName}...`);\n const result = await backend.index(projectRoot, { force: options.force });\n\n console.log(ansis.green(`\u2713 Indexing complete`));\n console.log(` Nodes: ${result.node_count}`);\n console.log(` Edges: ${result.edge_count}`);\n console.log(` Git HEAD: ${result.git_head}`);\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n ErrorCategory.SYSTEM\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Endpoints subcommand - list API endpoints from indexed project\n */\n analyzer\n .command(\"endpoints\")\n .description(\"List discovered API endpoints from indexed project\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer endpoints # List endpoints from active analyzer\n $ dr analyzer endpoints --json # Output as JSON\n $ dr analyzer endpoints --name cbm # List endpoints from specific analyzer`\n )\n .action(async (options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const status = await backend.status(projectRoot);\n if (!status.indexed) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` to index the project first\"]\n );\n }\n\n // Query for endpoints\n const endpoints = await backend.endpoints(projectRoot);\n\n // JSON output\n if (jsonMode) {\n console.log(JSON.stringify(endpoints, null, 2));\n return;\n }\n\n // Table output\n if (endpoints.length === 0) {\n console.log(ansis.yellow(\"No endpoints found\"));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`API Endpoints (${endpoints.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(135)));\n\n // Print header\n const methodWidth = 8;\n const pathWidth = 20;\n const nameWidth = 18;\n const idFragmentWidth = 18;\n const symbolWidth = 18;\n const confidenceWidth = 12;\n const fileWidth = 25;\n\n console.log(\n ansis.cyan(\n `${\"Method\".padEnd(methodWidth)} ${\"Path\".padEnd(pathWidth)} ${\"Name\".padEnd(nameWidth)} ${\"ID Fragment\".padEnd(idFragmentWidth)} ${\"Symbol\".padEnd(symbolWidth)} ${\"Confidence\".padEnd(confidenceWidth)} File`\n )\n );\n console.log(ansis.dim(\"\u2500\".repeat(135)));\n\n // Print each endpoint\n for (const endpoint of endpoints) {\n const method = endpoint.http_method.padEnd(methodWidth);\n const path = endpoint.http_path.substring(0, pathWidth).padEnd(pathWidth);\n const name = endpoint.suggested_name.substring(0, nameWidth).padEnd(nameWidth);\n const idFragment = endpoint.suggested_id_fragment.substring(0, idFragmentWidth).padEnd(idFragmentWidth);\n const symbol = endpoint.source_symbol.substring(0, symbolWidth).padEnd(symbolWidth);\n const confidence = endpoint.confidence.toUpperCase().padEnd(confidenceWidth);\n const file = endpoint.source_file.substring(0, fileWidth);\n\n console.log(`${method} ${path} ${name} ${idFragment} ${symbol} ${confidence} ${ansis.dim(file)}`);\n }\n\n console.log(ansis.dim(\"\u2500\".repeat(135)));\n console.log(ansis.dim(`Total: ${endpoints.length} endpoint(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Services subcommand - query for services/components in indexed project\n */\n analyzer\n .command(\"services\")\n .description(\"Query for services/components in the indexed project\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--layer <layer>\", \"Filter by layer (e.g., 'application')\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer services # List all services\n $ dr analyzer services --layer application\n $ dr analyzer services --json # Output as JSON`\n )\n .action(async (options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for services\n let services = await backend.services(projectRoot);\n\n // Filter by layer if specified\n if (options.layer) {\n services = services.filter(s => s.suggested_layer === options.layer);\n }\n\n // JSON output\n if (jsonMode) {\n console.log(JSON.stringify(services, null, 2));\n return;\n }\n\n // Table output\n if (services.length === 0) {\n console.log(ansis.yellow(\"No services found\"));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Services (${services.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(120)));\n\n // Print header\n const nameWidth = 20;\n const layerWidth = 15;\n const typeWidth = 18;\n const symbolWidth = 20;\n const confidenceWidth = 12;\n const fileWidth = 25;\n\n console.log(\n ansis.cyan(\n `${\"Name\".padEnd(nameWidth)} ${\"Layer\".padEnd(layerWidth)} ${\"Type\".padEnd(typeWidth)} ${\"Symbol\".padEnd(symbolWidth)} ${\"Confidence\".padEnd(confidenceWidth)} File`\n )\n );\n console.log(ansis.dim(\"\u2500\".repeat(120)));\n\n // Print each service\n for (const service of services) {\n const name = service.suggested_name.substring(0, nameWidth).padEnd(nameWidth);\n const layer = service.suggested_layer.substring(0, layerWidth).padEnd(layerWidth);\n const type = service.suggested_element_type.substring(0, typeWidth).padEnd(typeWidth);\n const symbol = service.source_symbol.substring(0, symbolWidth).padEnd(symbolWidth);\n const confidence = service.confidence.toUpperCase().padEnd(confidenceWidth);\n const file = service.source_file.substring(0, fileWidth);\n\n console.log(`${name} ${layer} ${type} ${symbol} ${confidence} ${ansis.dim(file)}`);\n }\n\n console.log(ansis.dim(\"\u2500\".repeat(120)));\n console.log(ansis.dim(`Total: ${services.length} service(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Datastores subcommand - query for datastores/databases inferred from code\n */\n analyzer\n .command(\"datastores\")\n .description(\"Query for datastores/databases inferred from code analysis\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer datastores # List all inferred datastores\n $ dr analyzer datastores --json # Output as JSON`\n )\n .action(async (options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for datastores\n const datastores = await backend.datastores(projectRoot);\n\n // JSON output\n if (jsonMode) {\n console.log(JSON.stringify(datastores, null, 2));\n return;\n }\n\n // Table output\n if (datastores.length === 0) {\n console.log(ansis.yellow(\"No datastores found\"));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Datastores (${datastores.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(100)));\n\n // Print each datastore\n for (const ds of datastores) {\n console.log(` ${ansis.cyan(ds.suggested_name)}`);\n console.log(` Inferred from:`);\n for (const evidence of ds.inferred_from) {\n console.log(` - ${evidence.source_file}: ${evidence.import_pattern}`);\n }\n if (ds.notes) {\n console.log(` Notes: ${ds.notes}`);\n }\n console.log(\"\");\n }\n\n console.log(ansis.dim(`Total: ${datastores.length} datastore(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Callers subcommand - query for callers of a specific symbol\n */\n analyzer\n .command(\"callers <qualified-name>\")\n .description(\"Query for callers of a specific function or symbol\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--depth <n>\", \"Maximum depth for call graph traversal (default: 3, max: 10)\", \"3\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer callers com.example.Service.handleRequest\n $ dr analyzer callers com.example.Service.handleRequest --depth 5\n $ dr analyzer callers com.example.Service.handleRequest --json`\n )\n .action(async (qualifiedName, options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Validate depth\n const depth = parseInt(options.depth, 10);\n if (isNaN(depth) || depth < 1) {\n throw new CLIError(\n \"Invalid --depth value: must be a positive integer\",\n ErrorCategory.USER\n );\n }\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for callers\n const callers = await backend.callers(projectRoot, qualifiedName, depth);\n\n // JSON output\n if (jsonMode) {\n console.log(JSON.stringify(callers, null, 2));\n return;\n }\n\n // Table output\n if (callers.length === 0) {\n console.log(ansis.yellow(`No callers found for ${qualifiedName}`));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Callers of ${ansis.cyan(qualifiedName)} (${callers.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(100)));\n\n // Print each caller\n for (const caller of callers) {\n console.log(` ${ansis.bold(caller.qualified_name)}`);\n console.log(` File: ${caller.source_file}`);\n console.log(` Symbol: ${caller.source_symbol}`);\n console.log(` Depth: ${caller.depth}`);\n console.log(` Edge: ${caller.edge_type}`);\n console.log(\"\");\n }\n\n console.log(ansis.dim(`Total: ${callers.length} caller(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Callees subcommand - query for callees of a specific symbol\n */\n analyzer\n .command(\"callees <qualified-name>\")\n .description(\"Query for callees of a specific function or symbol\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--depth <n>\", \"Maximum depth for call graph traversal (default: 3, max: 10)\", \"3\")\n .option(\"--json\", \"Output as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer callees com.example.Service.handleRequest\n $ dr analyzer callees com.example.Service.handleRequest --depth 5\n $ dr analyzer callees com.example.Service.handleRequest --json`\n )\n .action(async (qualifiedName, options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Validate depth\n const depth = parseInt(options.depth, 10);\n if (isNaN(depth) || depth < 1) {\n throw new CLIError(\n \"Invalid --depth value: must be a positive integer\",\n ErrorCategory.USER\n );\n }\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Query for callees\n const callees = await backend.callees(projectRoot, qualifiedName, depth);\n\n // JSON output\n if (jsonMode) {\n console.log(JSON.stringify(callees, null, 2));\n return;\n }\n\n // Table output\n if (callees.length === 0) {\n console.log(ansis.yellow(`No callees found for ${qualifiedName}`));\n return;\n }\n\n console.log(\"\");\n console.log(ansis.bold(`Callees of ${ansis.cyan(qualifiedName)} (${callees.length} found):`));\n console.log(ansis.dim(\"\u2500\".repeat(100)));\n\n // Print each callee\n for (const callee of callees) {\n console.log(` ${ansis.bold(callee.qualified_name)}`);\n console.log(` File: ${callee.source_file}`);\n console.log(` Symbol: ${callee.source_symbol}`);\n console.log(` Depth: ${callee.depth}`);\n console.log(` Edge: ${callee.edge_type}`);\n console.log(\"\");\n }\n\n console.log(ansis.dim(`Total: ${callees.length} callee(s)`));\n console.log(\"\");\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Query subcommand - execute a raw query against the analyzer's graph\n * Documented as an advanced escape hatch for graph queries (not recommended for scripting)\n */\n analyzer\n .command(\"query <cypher>\")\n .description(\"Execute a raw Cypher query against the analyzer graph (advanced escape hatch)\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--json\", \"Output as JSON (default format for query results)\")\n .addHelpText(\n \"before\",\n `Advanced Escape Hatch: This command directly executes graph queries without validation or wrapping.\nUse for advanced analysis when standard commands don't meet your needs.\\n`\n )\n .addHelpText(\n \"after\",\n `\nQuery syntax depends on the analyzer backend (e.g., Cypher for graph analyzers).\nResults are always output as JSON.\n\nExamples:\n $ dr analyzer query \"MATCH (n) RETURN n LIMIT 10\"\n $ dr analyzer query \"MATCH (n:Service) RETURN n.name\"\n $ dr analyzer query \"MATCH (n) RETURN n LIMIT 10\" --json`\n )\n .action(async (cypher, options) => {\n try {\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Execute query\n const result = await backend.query(projectRoot, cypher);\n\n // Output format: JSON is the only reasonable format for arbitrary query results\n // The --json flag is accepted for consistency, but JSON is always the output format\n // (the flag currently has no effect as all query output is JSON)\n if (options.json === false) {\n // Explicit no-op: --json flag or its absence doesn't change behavior\n // Query results are always output as JSON regardless of flag\n }\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n\n /**\n * Verify subcommand - verify that graph-discovered routes align with model endpoints\n */\n analyzer\n .command(\"verify\")\n .description(\"Verify that graph-discovered routes align with model endpoints\")\n .option(\"--name <n>\", \"Analyzer name (defaults to active from session.json)\")\n .option(\"--layer <layer>\", \"Layer(s) to verify (can be used multiple times)\", (value, previous: string[] | undefined) => {\n return previous ? [...previous, value] : [value];\n })\n .option(\"--json\", \"Output as JSON\")\n .option(\"--format <format>\", \"Output format: text, json, markdown (default: text)\")\n .option(\"--output <path>\", \"Write report to file\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ dr analyzer verify # Verify api layer (default)\n $ dr analyzer verify --layer api # Explicitly specify api layer\n $ dr analyzer verify --json # Output as JSON to stdout\n $ dr analyzer verify --format markdown # Output as Markdown to stdout\n $ dr analyzer verify --output report.json # Save report to file (format inferred as JSON)\n $ dr analyzer verify --output report.md # Save report as Markdown`\n )\n .action(async (options) => {\n // Merge global --json flag if local one isn't set\n const jsonMode = options.json ?? program.opts().json;\n try {\n // Determine output format from --json flag, --format flag, or --output file extension\n let format: \"text\" | \"json\" | \"markdown\" = \"text\";\n if (jsonMode) {\n // Warn if both --json and --format are provided\n if (options.format) {\n console.warn(ansis.yellow(`\u26A0 Both --json and --format \"${options.format}\" were provided. Using --json format (--format is ignored).`));\n }\n format = \"json\";\n } else if (options.format) {\n const validFormats = [\"text\", \"json\", \"markdown\"];\n if (!validFormats.includes(options.format)) {\n throw new CLIError(\n `Invalid format: \"${options.format}\". Valid values are: ${validFormats.join(\", \")}.`,\n ErrorCategory.USER\n );\n }\n format = options.format as \"text\" | \"json\" | \"markdown\";\n } else if (options.output) {\n const ext = path.extname(options.output).toLowerCase();\n if (ext === \".json\") {\n format = \"json\";\n } else if (ext === \".md\") {\n format = \"markdown\";\n } else if (ext) {\n // Warn if file has unrecognized extension\n console.warn(ansis.yellow(`\u26A0 Unrecognized file extension \"${ext}\" in --output. Using text format by default.`));\n }\n }\n\n // Find project root\n const projectRoot = await findProjectRoot();\n if (!projectRoot) {\n throw new ModelNotFoundError();\n }\n\n // Validate layers - only api is supported in v1\n const requestedLayers = options.layer || [\"api\"];\n const apiLayers = requestedLayers.filter((layer: string) => layer === \"api\");\n const nonApiLayers = requestedLayers.filter((layer: string) => layer !== \"api\");\n\n // Report non-api layers as not available\n for (const layer of nonApiLayers) {\n console.log(ansis.dim(`No verification available for layer '${layer}'`));\n }\n\n // If no api layers to verify, exit cleanly\n if (apiLayers.length === 0) {\n return;\n }\n\n // Resolve analyzer name\n let analyzerName = options.name;\n if (!analyzerName) {\n const session = await readSession(projectRoot);\n if (!session) {\n throw new CLIError(\n \"No analyzer selected. Run `dr analyzer discover` first.\",\n ErrorCategory.USER\n );\n }\n analyzerName = session.active_analyzer;\n }\n\n // Get analyzer\n const registry = AnalyzerRegistry.getInstance();\n await registry.initialize();\n const backend = await registry.getAnalyzer(analyzerName);\n\n if (!backend) {\n throw new CLIError(\n `Analyzer not found: ${analyzerName}`,\n ErrorCategory.NOT_FOUND\n );\n }\n\n // Check if project is indexed\n const indexMeta = await readIndexMeta(projectRoot, analyzerName);\n if (!indexMeta) {\n throw new CLIError(\n \"Project not indexed\",\n ErrorCategory.USER,\n [\"Run `dr analyzer index` first\"]\n );\n }\n\n // Execute verification with changeset awareness enabled by default\n const report = await backend.verify(projectRoot, {\n layers: apiLayers,\n changesetAware: true,\n });\n\n const formatted = formatVerifyReport(report, { format });\n\n // Write to file if --output specified\n if (options.output) {\n const outputPath = path.resolve(options.output);\n await fs.writeFile(outputPath, formatted, \"utf-8\");\n console.log(ansis.green(`\u2713 Report written to ${outputPath}`));\n return;\n }\n\n // Print to stdout\n console.log(formatted);\n } catch (error) {\n if (error instanceof CLIError || error instanceof ModelNotFoundError) throw error;\n const cliError = new CLIError(\n error instanceof Error ? error.message : String(error),\n categorizeError(error)\n );\n if (error instanceof Error) {\n cliError.cause = error;\n }\n throw cliError;\n }\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["analyzerOptions", "installed", "discoveryResult", "path"]
7
7
  }
@@ -12,7 +12,7 @@ async function auditCommand(options) {
12
12
  const validAuditTypes = ["relationships", "nodes", "all"];
13
13
  if (options.type && !validAuditTypes.includes(options.type))
14
14
  throw new CLIError(`Invalid audit type: "${options.type}". Valid values are: ${validAuditTypes.join(", ")}.`);
15
- const auditType = options.type ?? "relationships";
15
+ const auditType = options.type ?? "relationships", projectRoot = options.projectRoot ?? process.cwd();
16
16
  let format = "text";
17
17
  if (options.format)
18
18
  format = options.format;
@@ -25,7 +25,7 @@ async function auditCommand(options) {
25
25
  const report = await new ModelNodeAuditOrchestrator().runAudit({
26
26
  layer: options.layer,
27
27
  verbose: options.verbose,
28
- projectRoot: process.cwd()
28
+ projectRoot
29
29
  });
30
30
  output = formatNodeAuditReport(report, { format, verbose: options.verbose });
31
31
  } else if (auditType === "all") {
@@ -34,12 +34,12 @@ async function auditCommand(options) {
34
34
  layer: options.layer,
35
35
  verbose: options.verbose,
36
36
  debug: options.debug,
37
- projectRoot: process.cwd()
37
+ projectRoot
38
38
  }),
39
39
  new ModelNodeAuditOrchestrator().runAudit({
40
40
  layer: options.layer,
41
41
  verbose: options.verbose,
42
- projectRoot: process.cwd()
42
+ projectRoot
43
43
  })
44
44
  ]);
45
45
  let relOutput, nodeOutput;
@@ -57,7 +57,7 @@ async function auditCommand(options) {
57
57
  layer: options.layer,
58
58
  verbose: options.verbose,
59
59
  debug: options.debug,
60
- projectRoot: process.cwd()
60
+ projectRoot
61
61
  });
62
62
  if (output = formatAuditReport(report, { format, verbose: options.verbose }), options.saveSnapshot) {
63
63
  options.debug && console.log(ansis.dim("Saving audit snapshot..."));
@@ -66,7 +66,7 @@ async function auditCommand(options) {
66
66
  }
67
67
  }
68
68
  if (options.output) {
69
- const outputPath = path.resolve(process.cwd(), options.output), outputDir = path.dirname(outputPath);
69
+ const outputPath = path.resolve(projectRoot, options.output), outputDir = path.dirname(outputPath);
70
70
  await ensureDir(outputDir), await writeFile(outputPath, output), console.log(ansis.green(`\u2713 Audit report written to ${options.output}`));
71
71
  } else
72
72
  console.log(output);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/commands/audit.ts"],
4
- "sourcesContent": ["/**\n * Audit command - Analyze relationship coverage, gaps, duplicates, and balance\n */\n\nimport ansis from \"ansis\";\nimport { writeFile, ensureDir } from \"../utils/file-io.js\";\nimport { getErrorMessage, CLIError } from \"../utils/errors.js\";\nimport {\n formatAuditReport,\n formatNodeAuditReport,\n AuditReportFormat,\n} from \"../export/audit-formatters.js\";\nimport { SnapshotStorage } from \"../audit/snapshot-storage.js\";\nimport { ModelAuditOrchestrator } from \"../audit/relationships/model/orchestrator.js\";\nimport { ModelNodeAuditOrchestrator } from \"../audit/nodes/model/orchestrator.js\";\nimport { formatDate } from \"../utils/date-utils.js\";\nimport path from \"path\";\n\nexport type AuditType = \"relationships\" | \"nodes\" | \"all\";\n\nexport interface AuditOptions {\n layer?: string;\n type?: AuditType;\n format?: AuditReportFormat;\n output?: string;\n verbose?: boolean;\n debug?: boolean;\n saveSnapshot?: boolean;\n}\n\n/**\n * Run the audit command\n */\nexport async function auditCommand(options: AuditOptions): Promise<void> {\n try {\n const validAuditTypes: AuditType[] = [\"relationships\", \"nodes\", \"all\"];\n if (options.type && !validAuditTypes.includes(options.type)) {\n throw new CLIError(\n `Invalid audit type: \"${options.type}\". Valid values are: ${validAuditTypes.join(\", \")}.`\n );\n }\n const auditType: AuditType = options.type ?? \"relationships\";\n\n // Determine output format\n let format: AuditReportFormat = \"text\";\n if (options.format) {\n format = options.format;\n } else if (options.output) {\n const ext = path.extname(options.output).toLowerCase();\n if (ext === \".json\") {\n format = \"json\";\n } else if (ext === \".md\") {\n format = \"markdown\";\n }\n }\n\n let output: string;\n\n if (auditType === \"nodes\") {\n // Node type audit - analyzes element types in the model\n const orchestrator = new ModelNodeAuditOrchestrator();\n const report = await orchestrator.runAudit({\n layer: options.layer,\n verbose: options.verbose,\n projectRoot: process.cwd(),\n });\n\n output = formatNodeAuditReport(report, { format, verbose: options.verbose });\n } else if (auditType === \"all\") {\n // Combined audit - run both independently; one failing does not suppress the other\n const [relResult, nodeResult] = await Promise.allSettled([\n new ModelAuditOrchestrator().runAudit({\n layer: options.layer,\n verbose: options.verbose,\n debug: options.debug,\n projectRoot: process.cwd(),\n }),\n new ModelNodeAuditOrchestrator().runAudit({\n layer: options.layer,\n verbose: options.verbose,\n projectRoot: process.cwd(),\n }),\n ]);\n\n let relOutput: string | undefined;\n let nodeOutput: string | undefined;\n\n if (relResult.status === \"fulfilled\") {\n relOutput = formatAuditReport(relResult.value, { format, verbose: options.verbose });\n } else {\n console.error(ansis.red(`\u26A0\uFE0F Relationship audit failed: ${getErrorMessage(relResult.reason)}`));\n }\n if (nodeResult.status === \"fulfilled\") {\n nodeOutput = formatNodeAuditReport(nodeResult.value, { format, verbose: options.verbose });\n } else {\n console.error(ansis.red(`\u26A0\uFE0F Node audit failed: ${getErrorMessage(nodeResult.reason)}`));\n }\n\n if (!relOutput && !nodeOutput) {\n throw new CLIError(\"Both audit types failed. See errors above.\");\n }\n\n if (format === \"json\") {\n const merged: Record<string, unknown> = {};\n if (relOutput) merged.relationships = JSON.parse(relOutput);\n if (nodeOutput) merged.nodes = JSON.parse(nodeOutput);\n output = JSON.stringify(merged, null, 2);\n } else {\n output = [relOutput, nodeOutput].filter(Boolean).join(\"\\n\\n\");\n }\n } else {\n // Default: relationships audit - analyzes the project's actual relationship instances\n const orchestrator = new ModelAuditOrchestrator();\n const report = await orchestrator.runAudit({\n layer: options.layer,\n verbose: options.verbose,\n debug: options.debug,\n projectRoot: process.cwd(),\n });\n\n output = formatAuditReport(report, { format, verbose: options.verbose });\n\n // Save snapshot if requested (relationships audit only)\n if (options.saveSnapshot) {\n if (options.debug) {\n console.log(ansis.dim(\"Saving audit snapshot...\"));\n }\n\n const storage = new SnapshotStorage();\n const metadata = await storage.save(report);\n\n console.log(ansis.green(`\u2713 Snapshot saved: ${metadata.id}`));\n console.log(ansis.dim(` Timestamp: ${formatDate(metadata.timestamp)}`));\n }\n }\n\n // Write to file or stdout\n if (options.output) {\n const outputPath = path.resolve(process.cwd(), options.output);\n const outputDir = path.dirname(outputPath);\n\n await ensureDir(outputDir);\n await writeFile(outputPath, output);\n\n console.log(ansis.green(`\u2713 Audit report written to ${options.output}`));\n } else {\n console.log(output);\n }\n } catch (error) {\n const message = getErrorMessage(error);\n if (options.debug) {\n console.error(error);\n }\n throw new CLIError(`Audit failed: ${message}`);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Audit command - Analyze relationship coverage, gaps, duplicates, and balance\n */\n\nimport ansis from \"ansis\";\nimport { writeFile, ensureDir } from \"../utils/file-io.js\";\nimport { getErrorMessage, CLIError } from \"../utils/errors.js\";\nimport {\n formatAuditReport,\n formatNodeAuditReport,\n AuditReportFormat,\n} from \"../export/audit-formatters.js\";\nimport { SnapshotStorage } from \"../audit/snapshot-storage.js\";\nimport { ModelAuditOrchestrator } from \"../audit/relationships/model/orchestrator.js\";\nimport { ModelNodeAuditOrchestrator } from \"../audit/nodes/model/orchestrator.js\";\nimport { formatDate } from \"../utils/date-utils.js\";\nimport path from \"path\";\n\nexport type AuditType = \"relationships\" | \"nodes\" | \"all\";\n\nexport interface AuditOptions {\n layer?: string;\n type?: AuditType;\n format?: AuditReportFormat;\n output?: string;\n verbose?: boolean;\n debug?: boolean;\n saveSnapshot?: boolean;\n projectRoot?: string;\n}\n\n/**\n * Run the audit command\n */\nexport async function auditCommand(options: AuditOptions): Promise<void> {\n try {\n const validAuditTypes: AuditType[] = [\"relationships\", \"nodes\", \"all\"];\n if (options.type && !validAuditTypes.includes(options.type)) {\n throw new CLIError(\n `Invalid audit type: \"${options.type}\". Valid values are: ${validAuditTypes.join(\", \")}.`\n );\n }\n const auditType: AuditType = options.type ?? \"relationships\";\n const projectRoot = options.projectRoot ?? process.cwd();\n\n // Determine output format\n let format: AuditReportFormat = \"text\";\n if (options.format) {\n format = options.format;\n } else if (options.output) {\n const ext = path.extname(options.output).toLowerCase();\n if (ext === \".json\") {\n format = \"json\";\n } else if (ext === \".md\") {\n format = \"markdown\";\n }\n }\n\n let output: string;\n\n if (auditType === \"nodes\") {\n // Node type audit - analyzes element types in the model\n const orchestrator = new ModelNodeAuditOrchestrator();\n const report = await orchestrator.runAudit({\n layer: options.layer,\n verbose: options.verbose,\n projectRoot,\n });\n\n output = formatNodeAuditReport(report, { format, verbose: options.verbose });\n } else if (auditType === \"all\") {\n // Combined audit - run both independently; one failing does not suppress the other\n const [relResult, nodeResult] = await Promise.allSettled([\n new ModelAuditOrchestrator().runAudit({\n layer: options.layer,\n verbose: options.verbose,\n debug: options.debug,\n projectRoot,\n }),\n new ModelNodeAuditOrchestrator().runAudit({\n layer: options.layer,\n verbose: options.verbose,\n projectRoot,\n }),\n ]);\n\n let relOutput: string | undefined;\n let nodeOutput: string | undefined;\n\n if (relResult.status === \"fulfilled\") {\n relOutput = formatAuditReport(relResult.value, { format, verbose: options.verbose });\n } else {\n console.error(ansis.red(`\u26A0\uFE0F Relationship audit failed: ${getErrorMessage(relResult.reason)}`));\n }\n if (nodeResult.status === \"fulfilled\") {\n nodeOutput = formatNodeAuditReport(nodeResult.value, { format, verbose: options.verbose });\n } else {\n console.error(ansis.red(`\u26A0\uFE0F Node audit failed: ${getErrorMessage(nodeResult.reason)}`));\n }\n\n if (!relOutput && !nodeOutput) {\n throw new CLIError(\"Both audit types failed. See errors above.\");\n }\n\n if (format === \"json\") {\n const merged: Record<string, unknown> = {};\n if (relOutput) merged.relationships = JSON.parse(relOutput);\n if (nodeOutput) merged.nodes = JSON.parse(nodeOutput);\n output = JSON.stringify(merged, null, 2);\n } else {\n output = [relOutput, nodeOutput].filter(Boolean).join(\"\\n\\n\");\n }\n } else {\n // Default: relationships audit - analyzes the project's actual relationship instances\n const orchestrator = new ModelAuditOrchestrator();\n const report = await orchestrator.runAudit({\n layer: options.layer,\n verbose: options.verbose,\n debug: options.debug,\n projectRoot,\n });\n\n output = formatAuditReport(report, { format, verbose: options.verbose });\n\n // Save snapshot if requested (relationships audit only)\n if (options.saveSnapshot) {\n if (options.debug) {\n console.log(ansis.dim(\"Saving audit snapshot...\"));\n }\n\n const storage = new SnapshotStorage();\n const metadata = await storage.save(report);\n\n console.log(ansis.green(`\u2713 Snapshot saved: ${metadata.id}`));\n console.log(ansis.dim(` Timestamp: ${formatDate(metadata.timestamp)}`));\n }\n }\n\n // Write to file or stdout\n if (options.output) {\n const outputPath = path.resolve(projectRoot, options.output);\n const outputDir = path.dirname(outputPath);\n\n await ensureDir(outputDir);\n await writeFile(outputPath, output);\n\n console.log(ansis.green(`\u2713 Audit report written to ${options.output}`));\n } else {\n console.log(output);\n }\n } catch (error) {\n const message = getErrorMessage(error);\n if (options.debug) {\n console.error(error);\n }\n throw new CLIError(`Audit failed: ${message}`);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }