@documentation-robotics/cli 0.2.0 → 0.4.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 (335) hide show
  1. package/README.md +46 -16
  2. package/dist/analysis/relationship-classifier.js +2 -9
  3. package/dist/analysis/relationship-classifier.js.map +2 -2
  4. package/dist/analyzers/active-analyzer.js +62 -0
  5. package/dist/analyzers/active-analyzer.js.map +7 -0
  6. package/dist/analyzers/call-graph-utils.js +2 -2
  7. package/dist/analyzers/call-graph-utils.js.map +2 -2
  8. package/dist/analyzers/cards/build.js +191 -0
  9. package/dist/analyzers/cards/build.js.map +7 -0
  10. package/dist/analyzers/cards/classify.js +42 -0
  11. package/dist/analyzers/cards/classify.js.map +7 -0
  12. package/dist/analyzers/cards/edge-index.js +44 -0
  13. package/dist/analyzers/cards/edge-index.js.map +7 -0
  14. package/dist/analyzers/cards/extract.js +138 -0
  15. package/dist/analyzers/cards/extract.js.map +7 -0
  16. package/dist/analyzers/cards/facts.js +46 -0
  17. package/dist/analyzers/cards/facts.js.map +7 -0
  18. package/dist/analyzers/cards/graph.js +42 -0
  19. package/dist/analyzers/cards/graph.js.map +7 -0
  20. package/dist/analyzers/cards/index.js +8 -0
  21. package/dist/analyzers/cards/index.js.map +7 -0
  22. package/dist/analyzers/cards/routes.js +96 -0
  23. package/dist/analyzers/cards/routes.js.map +7 -0
  24. package/dist/analyzers/cards/tier0.js +18 -0
  25. package/dist/analyzers/cards/tier0.js.map +7 -0
  26. package/dist/analyzers/cards/types.js +1 -0
  27. package/dist/analyzers/cards/types.js.map +7 -0
  28. package/dist/analyzers/cbm-analyzer.js +270 -174
  29. package/dist/analyzers/cbm-analyzer.js.map +2 -2
  30. package/dist/analyzers/cbm-responses.js +342 -0
  31. package/dist/analyzers/cbm-responses.js.map +7 -0
  32. package/dist/analyzers/code-changes.js +159 -0
  33. package/dist/analyzers/code-changes.js.map +7 -0
  34. package/dist/analyzers/edge-relationships.js +49 -0
  35. package/dist/analyzers/edge-relationships.js.map +7 -0
  36. package/dist/analyzers/extraction-plan.js +541 -0
  37. package/dist/analyzers/extraction-plan.js.map +7 -0
  38. package/dist/analyzers/index-job.js +229 -0
  39. package/dist/analyzers/index-job.js.map +7 -0
  40. package/dist/analyzers/mapping-loader.js +9 -0
  41. package/dist/analyzers/mapping-loader.js.map +2 -2
  42. package/dist/analyzers/tier0-rules.js +153 -0
  43. package/dist/analyzers/tier0-rules.js.map +7 -0
  44. package/dist/analyzers/types.js.map +1 -1
  45. package/dist/audit/relationships/ai/prompts.js +10 -10
  46. package/dist/audit/relationships/ai/prompts.js.map +2 -2
  47. package/dist/audit/relationships/analysis/layer-templates.js +52 -52
  48. package/dist/audit/relationships/analysis/layer-templates.js.map +1 -1
  49. package/dist/cli.js +23 -11
  50. package/dist/cli.js.map +2 -2
  51. package/dist/coding-agents/default-permissions.js +31 -1
  52. package/dist/coding-agents/default-permissions.js.map +2 -2
  53. package/dist/coding-agents/drbot-mcp.js +269 -0
  54. package/dist/coding-agents/drbot-mcp.js.map +7 -0
  55. package/dist/commands/add.js +7 -4
  56. package/dist/commands/add.js.map +2 -2
  57. package/dist/commands/analyzer.js +143 -40
  58. package/dist/commands/analyzer.js.map +2 -2
  59. package/dist/commands/changeset-verify.js +63 -0
  60. package/dist/commands/changeset-verify.js.map +7 -0
  61. package/dist/commands/changeset.js +80 -29
  62. package/dist/commands/changeset.js.map +2 -2
  63. package/dist/commands/delete.js +10 -4
  64. package/dist/commands/delete.js.map +2 -2
  65. package/dist/commands/farm.js +176 -60
  66. package/dist/commands/farm.js.map +2 -2
  67. package/dist/commands/init.js +9 -26
  68. package/dist/commands/init.js.map +2 -2
  69. package/dist/commands/mcp.js +40 -21
  70. package/dist/commands/mcp.js.map +3 -3
  71. package/dist/commands/relationship.js +208 -37
  72. package/dist/commands/relationship.js.map +2 -2
  73. package/dist/commands/reports.js +3 -3
  74. package/dist/commands/reports.js.map +2 -2
  75. package/dist/commands/update.js +52 -32
  76. package/dist/commands/update.js.map +2 -2
  77. package/dist/commands/upgrade.js +99 -103
  78. package/dist/commands/upgrade.js.map +3 -3
  79. package/dist/commands/validate.js +19 -3
  80. package/dist/commands/validate.js.map +2 -2
  81. package/dist/commands/version.js +1 -1
  82. package/dist/commands/visualize.js +34 -15
  83. package/dist/commands/visualize.js.map +2 -2
  84. package/dist/core/annotation-store.js +15 -5
  85. package/dist/core/annotation-store.js.map +2 -2
  86. package/dist/core/catalog-migration.js +34 -0
  87. package/dist/core/catalog-migration.js.map +7 -0
  88. package/dist/core/changeset-analysis.js +421 -0
  89. package/dist/core/changeset-analysis.js.map +7 -0
  90. package/dist/core/changeset-base-index.js +160 -0
  91. package/dist/core/changeset-base-index.js.map +7 -0
  92. package/dist/core/changeset-brief-compact.js +256 -0
  93. package/dist/core/changeset-brief-compact.js.map +7 -0
  94. package/dist/core/changeset-brief-delta.js +102 -0
  95. package/dist/core/changeset-brief-delta.js.map +7 -0
  96. package/dist/core/changeset-graph.js +281 -0
  97. package/dist/core/changeset-graph.js.map +7 -0
  98. package/dist/core/changeset-only-guard.js +32 -0
  99. package/dist/core/changeset-only-guard.js.map +7 -0
  100. package/dist/core/changeset-summary.js +68 -0
  101. package/dist/core/changeset-summary.js.map +7 -0
  102. package/dist/core/changeset-validator.js +66 -20
  103. package/dist/core/changeset-validator.js.map +2 -2
  104. package/dist/core/changeset-verify.js +848 -0
  105. package/dist/core/changeset-verify.js.map +7 -0
  106. package/dist/core/changeset.js +56 -9
  107. package/dist/core/changeset.js.map +2 -2
  108. package/dist/core/element-type-migration.js +145 -0
  109. package/dist/core/element-type-migration.js.map +7 -0
  110. package/dist/core/extraction-observability.js +161 -0
  111. package/dist/core/extraction-observability.js.map +7 -0
  112. package/dist/core/farm-manifest.js +12 -6
  113. package/dist/core/farm-manifest.js.map +2 -2
  114. package/dist/core/farm-sync-engine.js +1 -1
  115. package/dist/core/farm-sync-engine.js.map +2 -2
  116. package/dist/core/farm-sync-state.js +10 -2
  117. package/dist/core/farm-sync-state.js.map +2 -2
  118. package/dist/core/migration-registry.js +88 -47
  119. package/dist/core/migration-registry.js.map +2 -2
  120. package/dist/core/model-upgrade.js +102 -0
  121. package/dist/core/model-upgrade.js.map +7 -0
  122. package/dist/core/model.js +82 -30
  123. package/dist/core/model.js.map +2 -2
  124. package/dist/core/mutation-handler.js +71 -6
  125. package/dist/core/mutation-handler.js.map +2 -2
  126. package/dist/core/project-init.js +53 -0
  127. package/dist/core/project-init.js.map +7 -0
  128. package/dist/core/relationship-migration-table.js +6639 -0
  129. package/dist/core/relationship-migration-table.js.map +7 -0
  130. package/dist/core/relationship-migration.js +272 -0
  131. package/dist/core/relationship-migration.js.map +7 -0
  132. package/dist/core/relationship-prune.js +49 -0
  133. package/dist/core/relationship-prune.js.map +7 -0
  134. package/dist/core/relationship-staging.js +161 -0
  135. package/dist/core/relationship-staging.js.map +7 -0
  136. package/dist/core/relationships.js +26 -4
  137. package/dist/core/relationships.js.map +2 -2
  138. package/dist/core/report-data-model.js +7 -13
  139. package/dist/core/report-data-model.js.map +2 -2
  140. package/dist/core/staged-changeset-storage.js +145 -18
  141. package/dist/core/staged-changeset-storage.js.map +2 -2
  142. package/dist/core/staged-source-reference.js +28 -0
  143. package/dist/core/staged-source-reference.js.map +7 -0
  144. package/dist/core/staging-area.js +166 -24
  145. package/dist/core/staging-area.js.map +2 -2
  146. package/dist/core/upgrade-plan.js +117 -0
  147. package/dist/core/upgrade-plan.js.map +7 -0
  148. package/dist/core/virtual-projection.js +13 -5
  149. package/dist/core/virtual-projection.js.map +2 -2
  150. package/dist/export/archimate-exporter.js +1 -0
  151. package/dist/export/archimate-exporter.js.map +2 -2
  152. package/dist/generated/compiled-validators.js +2 -2
  153. package/dist/generated/compiled-validators.js.map +2 -2
  154. package/dist/generated/layer-registry.js +16 -16
  155. package/dist/generated/layer-registry.js.map +2 -2
  156. package/dist/generated/node-types.js +186 -168
  157. package/dist/generated/node-types.js.map +2 -2
  158. package/dist/generated/relationship-index.js +2468 -7913
  159. package/dist/generated/relationship-index.js.map +2 -2
  160. package/dist/integrations/claude_code/.claude-plugin/plugin.json +24 -0
  161. package/dist/integrations/claude_code/agents/dr-architect.md +30 -3
  162. package/dist/integrations/claude_code/agents/dr-extractor.md +8 -2
  163. package/dist/integrations/claude_code/commands/dr-analyzer.md +565 -0
  164. package/dist/integrations/claude_code/commands/dr-changeset.md +2 -1
  165. package/dist/integrations/claude_code/commands/dr-map.md +20 -1
  166. package/dist/integrations/claude_code/commands/dr-plan.md +66 -0
  167. package/dist/integrations/claude_code/commands/dr-relate.md +106 -96
  168. package/dist/integrations/claude_code/commands/dr-verify.md +45 -2
  169. package/dist/integrations/claude_code/docs/END_TO_END_WALKTHROUGH.md +14 -0
  170. package/dist/integrations/claude_code/docs/MCP_SERVER.md +47 -26
  171. package/dist/integrations/claude_code/docs/QUICK_START.md +37 -8
  172. package/dist/integrations/claude_code/docs/README.md +68 -2
  173. package/dist/integrations/claude_code/plugin-agents/dr-advisor.md +255 -0
  174. package/dist/integrations/claude_code/plugin-agents/dr-architect.md +306 -0
  175. package/dist/integrations/claude_code/skills/dr_01_motivation_layer/SKILL.md +93 -72
  176. package/dist/integrations/claude_code/skills/dr_02_business_layer/SKILL.md +163 -126
  177. package/dist/integrations/claude_code/skills/dr_03_product_layer/SKILL.md +161 -126
  178. package/dist/integrations/claude_code/skills/dr_04_security_layer/SKILL.md +153 -133
  179. package/dist/integrations/claude_code/skills/dr_05_application_layer/SKILL.md +129 -100
  180. package/dist/integrations/claude_code/skills/dr_06_technology_layer/SKILL.md +111 -94
  181. package/dist/integrations/claude_code/skills/dr_07_api_layer/SKILL.md +143 -157
  182. package/dist/integrations/claude_code/skills/dr_08_data_model_layer/SKILL.md +117 -33
  183. package/dist/integrations/claude_code/skills/dr_09_dataset_layer/SKILL.md +74 -25
  184. package/dist/integrations/claude_code/skills/dr_10_ux_layer/SKILL.md +88 -12
  185. package/dist/integrations/claude_code/skills/dr_11_navigation_layer/SKILL.md +83 -24
  186. package/dist/integrations/claude_code/skills/dr_12_apm_layer/SKILL.md +57 -12
  187. package/dist/integrations/claude_code/skills/dr_13_testing_layer/SKILL.md +95 -15
  188. package/dist/integrations/claude_code/skills/dr_change_planning/SKILL.md +178 -0
  189. package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +8 -0
  190. package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +6 -1
  191. package/dist/integrations/github_copilot/agents/dr-architect.md +3 -1
  192. package/dist/integrations/github_copilot/skills/dr_01_motivation_layer/SKILL.md +182 -102
  193. package/dist/integrations/github_copilot/skills/dr_02_business_layer/SKILL.md +266 -148
  194. package/dist/integrations/github_copilot/skills/dr_03_product_layer/SKILL.md +547 -86
  195. package/dist/integrations/github_copilot/skills/dr_04_security_layer/SKILL.md +164 -169
  196. package/dist/integrations/github_copilot/skills/dr_05_application_layer/SKILL.md +420 -150
  197. package/dist/integrations/github_copilot/skills/dr_06_technology_layer/SKILL.md +331 -138
  198. package/dist/integrations/github_copilot/skills/dr_07_api_layer/SKILL.md +265 -201
  199. package/dist/integrations/github_copilot/skills/dr_08_data_model_layer/SKILL.md +181 -58
  200. package/dist/integrations/github_copilot/skills/dr_09_dataset_layer/SKILL.md +209 -57
  201. package/dist/integrations/github_copilot/skills/dr_10_ux_layer/SKILL.md +277 -112
  202. package/dist/integrations/github_copilot/skills/dr_11_navigation_layer/SKILL.md +219 -70
  203. package/dist/integrations/github_copilot/skills/dr_12_apm_layer/SKILL.md +189 -105
  204. package/dist/integrations/github_copilot/skills/dr_13_testing_layer/SKILL.md +225 -102
  205. package/dist/integrations/github_copilot/skills/dr_change_planning/SKILL.md +177 -0
  206. package/dist/integrations/github_copilot/skills/dr_changeset_reviewer/SKILL.md +3 -0
  207. package/dist/integrations/hash-utils.js.map +2 -2
  208. package/dist/mcp/api-key-manager.js +14 -1
  209. package/dist/mcp/api-key-manager.js.map +2 -2
  210. package/dist/mcp/changeset-only.js +45 -0
  211. package/dist/mcp/changeset-only.js.map +7 -0
  212. package/dist/mcp/project-root.js +85 -0
  213. package/dist/mcp/project-root.js.map +7 -0
  214. package/dist/mcp/server-instructions.js +27 -0
  215. package/dist/mcp/server-instructions.js.map +7 -0
  216. package/dist/mcp/strict-schema.js +52 -0
  217. package/dist/mcp/strict-schema.js.map +7 -0
  218. package/dist/mcp/tool-registry.js +55 -5
  219. package/dist/mcp/tool-registry.js.map +2 -2
  220. package/dist/mcp/tools/changeset-analysis-tools.js +98 -0
  221. package/dist/mcp/tools/changeset-analysis-tools.js.map +7 -0
  222. package/dist/mcp/tools/changeset-commit.js +224 -0
  223. package/dist/mcp/tools/changeset-commit.js.map +7 -0
  224. package/dist/mcp/tools/changeset-editing.js +260 -0
  225. package/dist/mcp/tools/changeset-editing.js.map +7 -0
  226. package/dist/mcp/tools/changeset-lifecycle.js +83 -0
  227. package/dist/mcp/tools/changeset-lifecycle.js.map +7 -0
  228. package/dist/mcp/tools/changeset-shared.js +31 -0
  229. package/dist/mcp/tools/changeset-shared.js.map +7 -0
  230. package/dist/mcp/tools/changeset-show.js +17 -1
  231. package/dist/mcp/tools/changeset-show.js.map +2 -2
  232. package/dist/mcp/tools/changeset-verify.js +49 -0
  233. package/dist/mcp/tools/changeset-verify.js.map +7 -0
  234. package/dist/mcp/tools/codebase-extract.js +836 -0
  235. package/dist/mcp/tools/codebase-extract.js.map +7 -0
  236. package/dist/mcp/tools/codebase-index.js +125 -0
  237. package/dist/mcp/tools/codebase-index.js.map +7 -0
  238. package/dist/mcp/tools/codebase-shared.js +265 -0
  239. package/dist/mcp/tools/codebase-shared.js.map +7 -0
  240. package/dist/mcp/tools/codebase-verify.js +48 -0
  241. package/dist/mcp/tools/codebase-verify.js.map +7 -0
  242. package/dist/mcp/tools/index.js +34 -1
  243. package/dist/mcp/tools/index.js.map +2 -2
  244. package/dist/mcp/tools/model-add.js +191 -74
  245. package/dist/mcp/tools/model-add.js.map +2 -2
  246. package/dist/mcp/tools/model-delete.js +2 -2
  247. package/dist/mcp/tools/model-delete.js.map +2 -2
  248. package/dist/mcp/tools/model-search.js +14 -0
  249. package/dist/mcp/tools/model-search.js.map +2 -2
  250. package/dist/mcp/tools/model-show.js +29 -2
  251. package/dist/mcp/tools/model-show.js.map +2 -2
  252. package/dist/mcp/tools/model-trace.js +93 -30
  253. package/dist/mcp/tools/model-trace.js.map +2 -2
  254. package/dist/mcp/tools/model-update.js +46 -26
  255. package/dist/mcp/tools/model-update.js.map +2 -2
  256. package/dist/mcp/tools/model-validate.js +46 -4
  257. package/dist/mcp/tools/model-validate.js.map +2 -2
  258. package/dist/mcp/tools/project-status-collectors.js +381 -0
  259. package/dist/mcp/tools/project-status-collectors.js.map +7 -0
  260. package/dist/mcp/tools/project-status.js +237 -0
  261. package/dist/mcp/tools/project-status.js.map +7 -0
  262. package/dist/mcp/tools/project-tools.js +505 -0
  263. package/dist/mcp/tools/project-tools.js.map +7 -0
  264. package/dist/mcp/tools/relationship-tools.js +167 -0
  265. package/dist/mcp/tools/relationship-tools.js.map +7 -0
  266. package/dist/mcp/tools/review-open.js +210 -0
  267. package/dist/mcp/tools/review-open.js.map +7 -0
  268. package/dist/mcp/tools/shared.js +35 -4
  269. package/dist/mcp/tools/shared.js.map +2 -2
  270. package/dist/mcp/tools/spec-type.js +90 -0
  271. package/dist/mcp/tools/spec-type.js.map +7 -0
  272. package/dist/reports/model-report-orchestrator.js +31 -2
  273. package/dist/reports/model-report-orchestrator.js.map +2 -2
  274. package/dist/schemas/bundled/analyzers/cbm.json +1200 -70
  275. package/dist/schemas/bundled/analyzers/manifest.json +2 -2
  276. package/dist/schemas/bundled/api.json +1029 -1658
  277. package/dist/schemas/bundled/apm.json +499 -734
  278. package/dist/schemas/bundled/application.json +735 -371
  279. package/dist/schemas/bundled/base.json +3 -220
  280. package/dist/schemas/bundled/business.json +452 -366
  281. package/dist/schemas/bundled/data-model.json +395 -411
  282. package/dist/schemas/bundled/data-store.json +334 -558
  283. package/dist/schemas/bundled/manifest.json +18 -18
  284. package/dist/schemas/bundled/motivation.json +349 -368
  285. package/dist/schemas/bundled/navigation.json +415 -731
  286. package/dist/schemas/bundled/product.json +325 -159
  287. package/dist/schemas/bundled/security.json +864 -1232
  288. package/dist/schemas/bundled/technology.json +574 -703
  289. package/dist/schemas/bundled/testing.json +865 -1646
  290. package/dist/schemas/bundled/ux.json +739 -1352
  291. package/dist/server/schemas.js +8 -0
  292. package/dist/server/schemas.js.map +2 -2
  293. package/dist/server/server.js +686 -231
  294. package/dist/server/server.js.map +3 -3
  295. package/dist/server/viewer-registry.js +264 -0
  296. package/dist/server/viewer-registry.js.map +7 -0
  297. package/dist/server-entry.js +2 -1
  298. package/dist/server-entry.js.map +2 -2
  299. package/dist/telemetry/index.js +1 -1
  300. package/dist/utils/ansi-suppressor.js +6 -8
  301. package/dist/utils/ansi-suppressor.js.map +2 -2
  302. package/dist/utils/attribute-patch.js +41 -0
  303. package/dist/utils/attribute-patch.js.map +7 -0
  304. package/dist/utils/error-hints.js +29 -0
  305. package/dist/utils/error-hints.js.map +7 -0
  306. package/dist/utils/errors.js +9 -3
  307. package/dist/utils/errors.js.map +2 -2
  308. package/dist/utils/id-generator.js +5 -2
  309. package/dist/utils/id-generator.js.map +2 -2
  310. package/dist/utils/project-paths.js +26 -1
  311. package/dist/utils/project-paths.js.map +2 -2
  312. package/dist/utils/source-reference.js +64 -31
  313. package/dist/utils/source-reference.js.map +2 -2
  314. package/dist/utils/spec-version.js +2 -2
  315. package/dist/utils/spec-version.js.map +1 -1
  316. package/dist/validators/composed-reference-validator.js +5 -27
  317. package/dist/validators/composed-reference-validator.js.map +2 -2
  318. package/dist/validators/model-warnings.js +28 -0
  319. package/dist/validators/model-warnings.js.map +7 -0
  320. package/dist/validators/reference-validator.js +0 -7
  321. package/dist/validators/reference-validator.js.map +2 -2
  322. package/dist/validators/relationship-schema-validator.js +3 -3
  323. package/dist/validators/relationship-schema-validator.js.map +2 -2
  324. package/dist/validators/schema-validator.js +27 -9
  325. package/dist/validators/schema-validator.js.map +2 -2
  326. package/dist/validators/types.js.map +1 -1
  327. package/dist/viewer/README.md +6 -6
  328. package/dist/viewer/assets/main-CUOQGGRA.css +1 -0
  329. package/dist/viewer/assets/main-DvH3gYrI.js +84 -0
  330. package/dist/viewer/index.html +2 -2
  331. package/dist/viewer/manifest.json +10 -10
  332. package/dist/viewer/version.json +1 -1
  333. package/package.json +2 -1
  334. package/dist/viewer/assets/main-B7AOQXXX.js +0 -81
  335. package/dist/viewer/assets/main-vdrFrG7q.css +0 -1
@@ -1,3 +1,4 @@
1
+ import { Option } from "commander";
1
2
  import { intro, outro, select, isCancel } from "@clack/prompts";
2
3
  import ansis from "ansis";
3
4
  import { promises as fs } from "fs";
@@ -8,7 +9,10 @@ import { readSession, writeSession, writeStatus, readIndexMeta } from "../analyz
8
9
  import { CLIError, ModelNotFoundError, ErrorCategory, categorizeError } from "../utils/errors.js";
9
10
  import { findProjectRoot } from "../utils/project-paths.js";
10
11
  import { performDiscover } from "./discover-logic.js";
12
+ import { analyzerHomepage, getAnalyzerBackend, resolveAnalyzerName, splitVerifyLayers } from "../analyzers/active-analyzer.js";
13
+ import { finishIndexJob, INDEX_JOB_TIMEOUT_MS, markIndexJobPhase } from "../analyzers/index-job.js";
11
14
  import { formatVerifyReport } from "../export/verify-formatters.js";
15
+ import { Model } from "../core/model.js";
12
16
  function analyzerCommands(program) {
13
17
  const analyzer = program.command("analyzer").description("Manage analyzer discovery and indexing");
14
18
  analyzer.command("discover").description("Discover and select an analyzer").option("--json", "Output as JSON").option("--reselect", "Force re-selection even if analyzer already selected").addHelpText("after", `
@@ -131,11 +135,16 @@ Examples:
131
135
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND, ["Check the analyzer name with `dr analyzer discover`"]);
132
136
  const actualProjectRoot = await findProjectRoot();
133
137
  let status;
134
- if (actualProjectRoot ? status = await backend.status(actualProjectRoot) : status = {
135
- detected: await backend.detect(),
136
- indexed: !1,
137
- fresh: !1
138
- }, jsonMode) {
138
+ if (actualProjectRoot) {
139
+ const model = await Model.load(actualProjectRoot);
140
+ status = await backend.status(actualProjectRoot, { codebaseRoot: model.codebaseRoot });
141
+ } else
142
+ status = {
143
+ detected: await backend.detect(),
144
+ indexed: !1,
145
+ fresh: !1
146
+ };
147
+ if (jsonMode) {
139
148
  console.log(JSON.stringify(status, null, 2)), actualProjectRoot && await writeStatus(status, actualProjectRoot, analyzerName);
140
149
  return;
141
150
  }
@@ -146,39 +155,43 @@ Examples:
146
155
  const category = categorizeError(error), cliError = new CLIError(error instanceof Error ? error.message : String(error), category);
147
156
  throw error instanceof Error && (cliError.cause = error), cliError;
148
157
  }
149
- }), analyzer.command("index").description("Index the current project with the analyzer").option("--name <n>", "Analyzer name (defaults to active from session.json)").option("--force", "Force re-indexing even if index is fresh").addHelpText("after", `
158
+ }), analyzer.command("index").description("Index the current project with the analyzer").option("--name <n>", "Analyzer name (defaults to active from session.json)").option("--force", "Force re-indexing even if index is fresh").addOption(new Option("--job <id>", "Record the run in .dr/analyzers/index-job.json (set by codebase_index)").hideHelp()).addHelpText("after", `
150
159
  Examples:
151
160
  $ dr analyzer index # Index with active analyzer
152
161
  $ dr analyzer index --force # Force re-index
153
- $ dr analyzer index --name cbm # Index with specific analyzer`).action(async (options) => {
162
+ $ dr analyzer index --name cbm # Index with specific analyzer
163
+
164
+ With codebase-memory-mcp (cbm), each run first adds /documentation-robotics/ and /.dr/ to a
165
+ .cbmignore at the codebase root (creating it if needed, keeping your lines, and leaving alone a
166
+ folder you negate with !), so DR's model, changesets and analyzer state stay out of the index.
167
+ Commit .cbmignore with the code.`).action(async (options) => {
168
+ const jobId = options.job;
169
+ let projectRoot = null;
154
170
  try {
155
- const projectRoot = await findProjectRoot();
156
- if (!projectRoot)
171
+ if (projectRoot = await findProjectRoot(), !projectRoot)
157
172
  throw new ModelNotFoundError();
158
- let analyzerName = options.name;
159
- if (!analyzerName) {
160
- const session = await readSession(projectRoot);
161
- if (!session)
162
- throw new CLIError("No analyzer selected. Run `dr analyzer discover` first.", ErrorCategory.USER);
163
- analyzerName = session.active_analyzer;
164
- }
165
- const registry = AnalyzerRegistry.getInstance();
166
- await registry.initialize();
167
- const backend = await registry.getAnalyzer(analyzerName);
168
- if (!backend)
169
- throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND, ["Check the analyzer name with `dr analyzer discover`"]);
173
+ const analyzerName = await resolveAnalyzerName(projectRoot, options.name), backend = await getAnalyzerBackend(analyzerName, [
174
+ "Check the analyzer name with `dr analyzer discover`"
175
+ ]);
170
176
  if (!(await backend.detect()).installed) {
171
- const homepageUrl = (await MappingLoader.load(analyzerName)).getAnalyzerMetadata()?.homepage || "https://github.com/search?q=codebase-memory";
177
+ const homepageUrl = await analyzerHomepage(analyzerName);
172
178
  throw new CLIError(`Analyzer not installed: ${analyzerName}`, ErrorCategory.USER, [
173
179
  "Run `dr analyzer discover` to find available analyzers and installation instructions",
174
180
  `Visit: ${homepageUrl}`
175
181
  ]);
176
182
  }
177
- console.log(`Indexing project with ${analyzerName}...`);
178
- const result = await backend.index(projectRoot, { force: options.force });
179
- console.log(ansis.green("\u2713 Indexing complete")), console.log(` Nodes: ${result.node_count}`), console.log(` Edges: ${result.edge_count}`), console.log(` Git HEAD: ${result.git_head}`);
183
+ const model = await Model.load(projectRoot);
184
+ jobId && await markIndexJobPhase(projectRoot, jobId, "indexing"), console.log(`Indexing project with ${analyzerName}...`);
185
+ const result = await backend.index(projectRoot, {
186
+ force: options.force,
187
+ codebaseRoot: model.codebaseRoot,
188
+ // A background run has no caller waiting on it: give a large codebase the time it needs.
189
+ ...jobId ? { timeoutMs: INDEX_JOB_TIMEOUT_MS } : {}
190
+ });
191
+ jobId && await finishIndexJob(projectRoot, jobId, { result }), console.log(ansis.green("\u2713 Indexing complete")), console.log(` Nodes: ${result.node_count}`), console.log(` Edges: ${result.edge_count}`), console.log(` Git HEAD: ${result.git_head}`);
180
192
  } catch (error) {
181
- if (error instanceof CLIError || error instanceof ModelNotFoundError)
193
+ if (jobId && await finishIndexJob(projectRoot ?? process.cwd(), jobId, { error: describeJobError(error) }).catch(() => {
194
+ }), error instanceof CLIError || error instanceof ModelNotFoundError)
182
195
  throw error;
183
196
  const cliError = new CLIError(error instanceof Error ? error.message : String(error), ErrorCategory.SYSTEM);
184
197
  throw error instanceof Error && (cliError.cause = error), cliError;
@@ -205,9 +218,10 @@ Examples:
205
218
  const backend = await registry.getAnalyzer(analyzerName);
206
219
  if (!backend)
207
220
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
208
- if (!(await backend.status(projectRoot)).indexed)
221
+ const model = await Model.load(projectRoot);
222
+ if (!(await backend.status(projectRoot, { codebaseRoot: model.codebaseRoot })).indexed)
209
223
  throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` to index the project first"]);
210
- const endpoints = await backend.endpoints(projectRoot);
224
+ const endpoints = await backend.endpoints(projectRoot, { codebaseRoot: model.codebaseRoot });
211
225
  if (jsonMode) {
212
226
  console.log(JSON.stringify(endpoints, null, 2));
213
227
  return;
@@ -252,9 +266,10 @@ Examples:
252
266
  const backend = await registry.getAnalyzer(analyzerName);
253
267
  if (!backend)
254
268
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
269
+ const model = await Model.load(projectRoot);
255
270
  if (!await readIndexMeta(projectRoot, analyzerName))
256
271
  throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
257
- let services = await backend.services(projectRoot);
272
+ let services = await backend.services(projectRoot, { codebaseRoot: model.codebaseRoot });
258
273
  if (options.layer && (services = services.filter((s) => s.suggested_layer === options.layer)), jsonMode) {
259
274
  console.log(JSON.stringify(services, null, 2));
260
275
  return;
@@ -298,9 +313,10 @@ Examples:
298
313
  const backend = await registry.getAnalyzer(analyzerName);
299
314
  if (!backend)
300
315
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
316
+ const model = await Model.load(projectRoot);
301
317
  if (!await readIndexMeta(projectRoot, analyzerName))
302
318
  throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
303
- const datastores = await backend.datastores(projectRoot);
319
+ const datastores = await backend.datastores(projectRoot, { codebaseRoot: model.codebaseRoot });
304
320
  if (jsonMode) {
305
321
  console.log(JSON.stringify(datastores, null, 2));
306
322
  return;
@@ -348,9 +364,10 @@ Examples:
348
364
  const backend = await registry.getAnalyzer(analyzerName);
349
365
  if (!backend)
350
366
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
367
+ const model = await Model.load(projectRoot);
351
368
  if (!await readIndexMeta(projectRoot, analyzerName))
352
369
  throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
353
- const callers = await backend.callers(projectRoot, qualifiedName, depth);
370
+ const callers = await backend.callers(projectRoot, qualifiedName, depth, { codebaseRoot: model.codebaseRoot });
354
371
  if (jsonMode) {
355
372
  console.log(JSON.stringify(callers, null, 2));
356
373
  return;
@@ -394,9 +411,10 @@ Examples:
394
411
  const backend = await registry.getAnalyzer(analyzerName);
395
412
  if (!backend)
396
413
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
414
+ const model = await Model.load(projectRoot);
397
415
  if (!await readIndexMeta(projectRoot, analyzerName))
398
416
  throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
399
- const callees = await backend.callees(projectRoot, qualifiedName, depth);
417
+ const callees = await backend.callees(projectRoot, qualifiedName, depth, { codebaseRoot: model.codebaseRoot });
400
418
  if (jsonMode) {
401
419
  console.log(JSON.stringify(callees, null, 2));
402
420
  return;
@@ -441,9 +459,10 @@ Examples:
441
459
  const backend = await registry.getAnalyzer(analyzerName);
442
460
  if (!backend)
443
461
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
462
+ const model = await Model.load(projectRoot);
444
463
  if (!await readIndexMeta(projectRoot, analyzerName))
445
464
  throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
446
- const result = await backend.query(projectRoot, cypher);
465
+ const result = await backend.query(projectRoot, cypher, { codebaseRoot: model.codebaseRoot });
447
466
  options.json, console.log(JSON.stringify(result, null, 2));
448
467
  } catch (error) {
449
468
  if (error instanceof CLIError || error instanceof ModelNotFoundError)
@@ -476,11 +495,61 @@ Examples:
476
495
  const projectRoot = await findProjectRoot();
477
496
  if (!projectRoot)
478
497
  throw new ModelNotFoundError();
479
- const requestedLayers = options.layer || ["api"], apiLayers = requestedLayers.filter((layer) => layer === "api"), nonApiLayers = requestedLayers.filter((layer) => layer !== "api");
498
+ const { verifiable: apiLayers, unsupported: nonApiLayers } = splitVerifyLayers(options.layer);
480
499
  for (const layer of nonApiLayers)
481
500
  console.log(ansis.dim(`No verification available for layer '${layer}'`));
482
501
  if (apiLayers.length === 0)
483
502
  return;
503
+ const analyzerName = await resolveAnalyzerName(projectRoot, options.name), backend = await getAnalyzerBackend(analyzerName), model = await Model.load(projectRoot);
504
+ if (!await readIndexMeta(projectRoot, analyzerName))
505
+ throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
506
+ const report = await backend.verify(projectRoot, {
507
+ layers: apiLayers,
508
+ changesetAware: !0,
509
+ codebaseRoot: model.codebaseRoot
510
+ }), formatted = formatVerifyReport(report, { format });
511
+ if (options.output) {
512
+ const outputPath = path.resolve(options.output);
513
+ await fs.writeFile(outputPath, formatted, "utf-8"), console.log(ansis.green(`\u2713 Report written to ${outputPath}`));
514
+ return;
515
+ }
516
+ console.log(formatted);
517
+ } catch (error) {
518
+ if (error instanceof CLIError || error instanceof ModelNotFoundError)
519
+ throw error;
520
+ const cliError = new CLIError(error instanceof Error ? error.message : String(error), categorizeError(error));
521
+ throw error instanceof Error && (cliError.cause = error), cliError;
522
+ }
523
+ }), analyzer.command("classify").description("Classify the indexed project's symbols into model layers and types (Tier 0: rules only)").option("--name <n>", "Analyzer name (defaults to active from session.json)").option("--tier0-only", "Apply only the analyzer's Tier-0 rules: no model calls, no network (required for now)").option("--label <labels>", "Comma-separated analyzer labels to classify (default: Class, Interface, Function, Method, Module, Route and every label a rule names)").option("--file <glob>", "Only symbols in files matching this glob").option("--exclude <regex>", "Also leave out files matching this regular expression (build and vendored paths always are)").option("--limit <n>", "Stop after this many symbols").option("--cards", "Include each symbol's full card (source and graph neighbourhood) in JSON output").option("--output <file>", "Write the JSON report to a file").option("--json", "Output as JSON").addHelpText("after", `
524
+ Tier 0 is the first step of the classification cascade (docs/analyzers/CASCADE_DESIGN.md):
525
+ the analyzer's rules decide a symbol's layer and type, reject it as not a model element,
526
+ or narrow its choices for a later tier. Symbols no rule covers are reported as undecided.
527
+ Nothing is written to the model.
528
+
529
+ Examples:
530
+ $ dr analyzer classify --tier0-only
531
+ $ dr analyzer classify --tier0-only --json > tier0.json
532
+ $ dr analyzer classify --tier0-only --label Class,Method --file "src/main/**"
533
+ $ dr analyzer classify --tier0-only --cards --output tier0-cards.json`).action(async (options) => {
534
+ const jsonMode = options.json ?? program.opts().json;
535
+ try {
536
+ if (!options.tier0Only)
537
+ throw new CLIError("Only Tier-0 classification is available so far: pass --tier0-only", ErrorCategory.USER, ["Model-backed classification (Tier 1) needs the per-project opt-in and is not built yet"]);
538
+ let exclude;
539
+ if (options.exclude !== void 0)
540
+ try {
541
+ exclude = new RegExp(String(options.exclude));
542
+ } catch (e) {
543
+ throw new CLIError(`Invalid --exclude regular expression: ${e instanceof Error ? e.message : String(e)}`, ErrorCategory.USER);
544
+ }
545
+ let limit;
546
+ if (options.limit !== void 0 && (limit = Number(options.limit), !Number.isInteger(limit) || limit < 1))
547
+ throw new CLIError(`--limit must be a positive integer, got '${options.limit}'`, ErrorCategory.USER);
548
+ const labels = options.label ? String(options.label).split(",").map((l) => l.trim()).filter(Boolean) : void 0;
549
+ options.cards && !jsonMode && !options.output && console.error(ansis.yellow("--cards only affects JSON output: add --json or --output <file>"));
550
+ const projectRoot = await findProjectRoot();
551
+ if (!projectRoot)
552
+ throw new ModelNotFoundError();
484
553
  let analyzerName = options.name;
485
554
  if (!analyzerName) {
486
555
  const session = await readSession(projectRoot);
@@ -493,18 +562,46 @@ Examples:
493
562
  const backend = await registry.getAnalyzer(analyzerName);
494
563
  if (!backend)
495
564
  throw new CLIError(`Analyzer not found: ${analyzerName}`, ErrorCategory.NOT_FOUND);
565
+ if (!backend.classify)
566
+ throw new CLIError(`The ${analyzerName} analyzer does not support classification`, ErrorCategory.USER);
496
567
  if (!await readIndexMeta(projectRoot, analyzerName))
497
568
  throw new CLIError("Project not indexed", ErrorCategory.USER, ["Run `dr analyzer index` first"]);
498
- const report = await backend.verify(projectRoot, {
499
- layers: apiLayers,
500
- changesetAware: !0
501
- }), formatted = formatVerifyReport(report, { format });
569
+ const model = await Model.load(projectRoot), showProgress = !jsonMode && !options.output && process.stderr.isTTY, report = await backend.classify(projectRoot, {
570
+ codebaseRoot: model.codebaseRoot,
571
+ labels,
572
+ filePattern: options.file,
573
+ exclude,
574
+ limit,
575
+ includeCards: !!options.cards,
576
+ onProgress: showProgress ? (done, total) => {
577
+ (done % 50 === 0 || done === total) && process.stderr.write(`\r ${done}/${total} symbols`), done === total && process.stderr.write(`
578
+ `);
579
+ } : void 0
580
+ });
502
581
  if (options.output) {
503
582
  const outputPath = path.resolve(options.output);
504
- await fs.writeFile(outputPath, formatted, "utf-8"), console.log(ansis.green(`\u2713 Report written to ${outputPath}`));
583
+ await fs.writeFile(outputPath, JSON.stringify(report, null, 2) + `
584
+ `, "utf-8"), jsonMode || console.log(ansis.green(`\u2713 Report written to ${outputPath}`));
585
+ }
586
+ if (jsonMode) {
587
+ console.log(JSON.stringify(report, null, 2));
505
588
  return;
506
589
  }
507
- console.log(formatted);
590
+ const { summary } = report, pct = (n) => summary.cards ? `${(100 * n / summary.cards).toFixed(0)}%` : "0%";
591
+ console.log(""), console.log(ansis.bold(`Tier-0 classification: ${summary.cards} symbols, ${report.rules} rules`)), console.log(ansis.dim("\u2500".repeat(60))), console.log(` ${ansis.green("decided")} ${String(summary.decided).padStart(6)} ${pct(summary.decided)}`), console.log(` ${ansis.yellow("rejected")} ${String(summary.rejected).padStart(6)} ${pct(summary.rejected)} (not model elements)`), console.log(` ${ansis.cyan("narrowed")} ${String(summary.narrowed).padStart(6)} ${pct(summary.narrowed)} (choices restricted for Tier 1)`), console.log(` ${ansis.dim("undecided")} ${String(summary.undecided).padStart(6)} ${pct(summary.undecided)}`), summary.no_source && console.log(ansis.yellow(` ${summary.no_source} symbol(s) had no source, so rules that read the declaration could not apply`));
592
+ const targets = Object.entries(summary.by_target).sort((a, b) => b[1] - a[1]);
593
+ if (targets.length) {
594
+ console.log(""), console.log(ansis.bold("Decided, by type:"));
595
+ for (const [target, n] of targets)
596
+ console.log(` ${target.padEnd(40)} ${String(n).padStart(6)}`);
597
+ }
598
+ const rules = Object.entries(summary.by_rule).sort((a, b) => b[1] - a[1]);
599
+ if (rules.length) {
600
+ console.log(""), console.log(ansis.bold("Matches, by rule:"));
601
+ for (const [rule, n] of rules)
602
+ console.log(` ${rule.padEnd(40)} ${String(n).padStart(6)}`);
603
+ }
604
+ console.log(ansis.dim("\u2500".repeat(60))), console.log(ansis.dim("Per-symbol outcomes: --json or --output <file>")), console.log("");
508
605
  } catch (error) {
509
606
  if (error instanceof CLIError || error instanceof ModelNotFoundError)
510
607
  throw error;
@@ -513,6 +610,12 @@ Examples:
513
610
  }
514
611
  });
515
612
  }
613
+ function describeJobError(error) {
614
+ const message = error instanceof Error ? error.message : String(error), suggestions = error instanceof CLIError ? error.suggestions ?? [] : [];
615
+ return suggestions.length > 0 ? `${message}
616
+ ${suggestions.map((s) => `- ${s}`).join(`
617
+ `)}` : message;
618
+ }
516
619
  export {
517
620
  analyzerCommands
518
621
  };