@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
@@ -4,12 +4,14 @@ import { StagingAreaManager } from "../core/staging-area.js";
4
4
  import { ChangesetExporter } from "../core/changeset-exporter.js";
5
5
  import { StagedChangesetStorage } from "../core/staged-changeset-storage.js";
6
6
  import { ValidationFormatter } from "../validators/validation-formatter.js";
7
+ import { Option } from "commander";
7
8
  import * as prompts from "@clack/prompts";
8
9
  import path from "path";
9
10
  import { isTelemetryEnabled, startSpan, endSpan, startActiveSpan } from "../telemetry/index.js";
10
- import { getErrorMessage, handleSuccess, handleInfo, handleWarning } from "../utils/errors.js";
11
+ import { CLIError, ErrorCategory, getErrorMessage, handleSuccess, handleInfo, handleWarning } from "../utils/errors.js";
11
12
  import { isJson } from "../utils/globals.js";
12
13
  import { findElementLayer } from "../utils/element-utils.js";
14
+ import { changesetVerifyCommand } from "./changeset-verify.js";
13
15
  function generateImportedChangesetId() {
14
16
  return `imported-${Date.now()}`;
15
17
  }
@@ -19,7 +21,7 @@ async function changesetCreateCommand(name, options) {
19
21
  "changeset.hasDescription": !!options.description
20
22
  }) : null;
21
23
  try {
22
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model);
24
+ const model = await Model.load(options.model, { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model);
23
25
  await manager.load(name) && (isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: `Changeset '${name}' already exists` })) : console.error(ansis.red(`Error: Changeset '${name}' already exists`)), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "Changeset already exists" }), endSpan(span), process.exit(1));
24
26
  let description = options.description;
25
27
  if (!description) {
@@ -55,7 +57,7 @@ async function changesetCreateCommand(name, options) {
55
57
  async function changesetListCommand(options = {}) {
56
58
  const span = isTelemetryEnabled ? startSpan("changeset.list") : null;
57
59
  try {
58
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), changesets = await new StagingAreaManager(model.rootPath, model).list();
60
+ const model = await Model.load(options.model, { lazyLoad: !0 }), changesets = await new StagingAreaManager(model.rootPath, model).list();
59
61
  if (isTelemetryEnabled && span && span.setAttribute("changeset.count", changesets.length), changesets.length === 0) {
60
62
  console.log(ansis.yellow("No changesets found")), console.log(), isTelemetryEnabled && span && span.setStatus({ code: 0 }), endSpan(span);
61
63
  return;
@@ -83,6 +85,14 @@ Changesets (${changesets.length}):
83
85
  endSpan(span);
84
86
  }
85
87
  }
88
+ function reportCommitValidation(result, details) {
89
+ if (result.validation.ran === !1) {
90
+ delete details.validationPassed, details.validationSkipped = !0, isJson() || console.log(ansis.yellow("\u26A0 Validation skipped (--no-validate); run 'dr validate' to check the result"));
91
+ return;
92
+ }
93
+ const preExisting = result.validation.preExistingErrors ?? 0;
94
+ details.preExistingErrors = preExisting, preExisting > 0 && (details.preExistingSample = result.validation.preExistingSample ?? [], isJson() || console.log(ansis.yellow(`\u26A0 ${preExisting} validation error(s) already in the base model were ignored; the changeset introduced none. Run 'dr validate' to see them.`)));
95
+ }
86
96
  async function changesetApplyCommand(name, options) {
87
97
  const span = isTelemetryEnabled ? startSpan("changeset.apply", {
88
98
  "changeset.name": name,
@@ -90,7 +100,7 @@ async function changesetApplyCommand(name, options) {
90
100
  "apply.force": options?.force === !0
91
101
  }) : null;
92
102
  try {
93
- const model = await Model.load(options?.model || process.cwd(), { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
103
+ const model = await Model.load(options?.model, { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
94
104
  if (changeset || (isJson() ? console.log(JSON.stringify({ status: "error", code: 2, message: `Changeset '${name}' not found` })) : console.error(ansis.red(`Error: Changeset '${name}' not found`)), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "Changeset not found" }), endSpan(span), process.exit(1)), isTelemetryEnabled && span && (span.setAttribute("changeset.id", changeset.id), span.setAttribute("changeset.changeCount", changeset.changes.length)), !isJson()) {
95
105
  console.log(ansis.bold(`
96
106
  Applying changeset: ${ansis.cyan(name)}
@@ -120,7 +130,7 @@ Applying changeset: ${ansis.cyan(name)}
120
130
  failed: result.failed,
121
131
  validationPassed: result.validation.passed
122
132
  };
123
- if (result.failed > 0 && (applyDetails.errors = result.validation.errors, !isJson())) {
133
+ if (reportCommitValidation(result, applyDetails), result.failed > 0 && (applyDetails.errors = result.validation.errors, !isJson())) {
124
134
  handleInfo(ansis.red(`\u2717 Failed to apply ${result.failed} change(s):`));
125
135
  for (const error of result.validation.errors)
126
136
  handleInfo(ansis.dim(` - ${error}`));
@@ -144,7 +154,7 @@ async function changesetRevertCommand(name, options = {}) {
144
154
  "changeset.name": name
145
155
  }) : null;
146
156
  try {
147
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
157
+ const model = await Model.load(options.model, { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
148
158
  changeset || (isJson() ? console.log(JSON.stringify({ status: "error", code: 2, message: `Changeset '${name}' not found` })) : console.error(ansis.red(`Error: Changeset '${name}' not found`)), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "Changeset not found" }), endSpan(span), process.exit(1)), isTelemetryEnabled && span && (span.setAttribute("changeset.id", changeset.id), span.setAttribute("changeset.changeCount", changeset.changes.length)), isJson() || (console.log(ansis.bold(`
149
159
  Reverting changeset: ${ansis.cyan(name)}
150
160
  `)), console.log(ansis.dim(`Changes to discard: ${changeset.changes.length}`)));
@@ -173,7 +183,7 @@ async function changesetActivateCommand(name, options = {}) {
173
183
  "changeset.name": name
174
184
  }) : null;
175
185
  try {
176
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
186
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
177
187
  changeset || (isJson() ? console.log(JSON.stringify({ status: "error", code: 2, message: `Changeset '${name}' not found` })) : console.error(ansis.red(`Error: Changeset '${name}' not found`)), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "Changeset not found" }), endSpan(span), process.exit(1)), await manager.setActive(name), handleSuccess(`Activated changeset: ${ansis.bold(name)}`, {
178
188
  changesetName: name,
179
189
  changesetId: changeset.id
@@ -190,7 +200,7 @@ async function changesetActivateCommand(name, options = {}) {
190
200
  async function changesetDeactivateCommand(options = {}) {
191
201
  const span = isTelemetryEnabled ? startSpan("changeset.deactivate") : null;
192
202
  try {
193
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), active = await manager.getActiveId();
203
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), active = await manager.getActiveId();
194
204
  if (!active) {
195
205
  handleInfo(ansis.yellow("No active changeset")), isTelemetryEnabled && span && (span.setAttribute("changeset.wasActive", !1), span.setStatus({ code: 0 })), endSpan(span);
196
206
  return;
@@ -216,7 +226,7 @@ async function changesetDeleteCommand(name, options) {
216
226
  "delete.force": options.force === !0
217
227
  }) : null;
218
228
  try {
219
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
229
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), changeset = await manager.load(name);
220
230
  if (changeset || (isJson() ? console.log(JSON.stringify({ status: "error", code: 2, message: `Changeset '${name}' not found` })) : console.error(ansis.red(`Error: Changeset '${name}' not found`)), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "Changeset not found" }), endSpan(span), process.exit(1)), await manager.getActiveId() === changeset.id && (isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: `Cannot delete active changeset '${name}'` })) : (console.error(ansis.red(`Error: Cannot delete active changeset '${name}'`)), console.log(ansis.dim(" Run `dr changeset deactivate` first"))), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "Cannot delete active changeset" }), endSpan(span), process.exit(1)), !options.force) {
221
231
  const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
222
232
  if (isTelemetryEnabled && span && span.setAttribute("cli.interactive", isInteractive), isInteractive) {
@@ -248,7 +258,7 @@ async function changesetDeleteCommand(name, options) {
248
258
  async function changesetStatusCommand(options = {}) {
249
259
  const span = isTelemetryEnabled ? startSpan("changeset.status") : null;
250
260
  try {
251
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), active = await manager.getActiveId();
261
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), active = await manager.getActiveId();
252
262
  if (!active) {
253
263
  console.log(ansis.dim("No active changeset")), isTelemetryEnabled && span && (span.setAttribute("changeset.hasActive", !1), span.setStatus({ code: 0 })), endSpan(span);
254
264
  return;
@@ -277,7 +287,7 @@ async function changesetStagedCommand(options) {
277
287
  "staged.layer": options.layer
278
288
  }) : null;
279
289
  try {
280
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangeset = await manager.getActiveId();
290
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangeset = await manager.getActiveId();
281
291
  if (!activeChangeset) {
282
292
  isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: "No active changeset" })) : console.error(ansis.red("Error: No active changeset")), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "No active changeset" }), endSpan(span);
283
293
  return;
@@ -327,7 +337,7 @@ Staged Changes (${changes.length}):
327
337
  async function changesetExplicitStageCommand(elementId, options = {}) {
328
338
  const span = isTelemetryEnabled ? startSpan("changeset.stage-explicit", { "stage.elementId": elementId }) : null;
329
339
  try {
330
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
340
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
331
341
  if (!activeChangesetId) {
332
342
  isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: "No active changeset" })) : console.error(ansis.red("Error: No active changeset")), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "No active changeset" }), endSpan(span);
333
343
  return;
@@ -361,7 +371,7 @@ async function changesetUnstageCommand(elementId, options = {}) {
361
371
  "unstage.elementId": elementId
362
372
  }) : null;
363
373
  try {
364
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
374
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
365
375
  if (!activeChangesetId) {
366
376
  isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: "No active changeset" })) : console.error(ansis.red("Error: No active changeset")), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "No active changeset" }), endSpan(span);
367
377
  return;
@@ -395,7 +405,7 @@ async function changesetDiscardCommand(elementId, options = {}) {
395
405
  "discard.all": !elementId
396
406
  }) : null;
397
407
  try {
398
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
408
+ const model = await Model.load(options.model, { lazyLoad: !0 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
399
409
  if (!activeChangesetId) {
400
410
  isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: "No active changeset" })) : console.error(ansis.red("Error: No active changeset")), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "No active changeset" }), endSpan(span);
401
411
  return;
@@ -445,7 +455,7 @@ async function changesetPreviewCommand(options) {
445
455
  "preview.layer": options.layer
446
456
  }) : null;
447
457
  try {
448
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
458
+ const model = await Model.load(options.model, { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
449
459
  if (!activeChangesetId) {
450
460
  console.error(ansis.red("Error: No active changeset")), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "No active changeset" }), endSpan(span);
451
461
  return;
@@ -498,7 +508,7 @@ async function changesetDiffCommand(options) {
498
508
  "diff.layer": options.layer
499
509
  }) : null;
500
510
  try {
501
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
511
+ const model = await Model.load(options.model, { lazyLoad: !1 }), manager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await manager.getActiveId();
502
512
  if (!activeChangesetId) {
503
513
  console.error(ansis.red("Error: No active changeset")), isTelemetryEnabled && span && span.setStatus({ code: 2, message: "No active changeset" }), endSpan(span);
504
514
  return;
@@ -533,10 +543,30 @@ Diff: Base Model vs Staged Changes
533
543
  endSpan(span);
534
544
  }
535
545
  }
536
- async function changesetCommitCommand(options) {
546
+ async function changesetCommitCommand(nameOrId, options) {
547
+ let restoreActive = null;
548
+ const restore = async () => {
549
+ if (!restoreActive)
550
+ return;
551
+ const { rootPath, previous } = restoreActive;
552
+ restoreActive = null;
553
+ const probe = await Model.load(rootPath, { lazyLoad: !0 }), manager = new StagingAreaManager(probe.rootPath, probe), prior = previous ? await manager.load(previous) : null;
554
+ prior?.status === "staged" ? (await manager.setActive(previous), isJson() || console.log(ansis.dim(`Changeset '${prior.name}' is active again.`))) : await manager.clearActive();
555
+ };
537
556
  await startActiveSpan("changeset.commit", async (span) => {
538
557
  try {
539
- const model = await Model.load(options?.model || process.cwd(), { lazyLoad: !1 }), stagingManager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await stagingManager.getActiveId();
558
+ if (nameOrId) {
559
+ const probe = await Model.load(options?.model, { lazyLoad: !0 }), probeManager = new StagingAreaManager(probe.rootPath, probe), target = await probeManager.load(nameOrId);
560
+ if (!target || !target.id)
561
+ throw new CLIError(`Changeset '${nameOrId}' not found`, ErrorCategory.USER, [
562
+ 'Run "dr changeset list" to see changesets by name and id'
563
+ ]);
564
+ if (target.status !== "staged")
565
+ throw new CLIError(`Changeset '${target.name}' is ${target.status}; only a staged changeset can be committed`, ErrorCategory.USER, ['Run "dr changeset list" to find a staged changeset']);
566
+ const activeId = await probeManager.getActiveId();
567
+ activeId !== target.id && (restoreActive = { rootPath: probe.rootPath, previous: activeId }, await probeManager.setActive(target.id));
568
+ }
569
+ const model = await Model.load(options?.model, { lazyLoad: !1 }), stagingManager = new StagingAreaManager(model.rootPath, model), activeChangesetId = await stagingManager.getActiveId();
540
570
  if (!activeChangesetId) {
541
571
  isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: "No active changeset" })) : console.error(ansis.red("Error: No active changeset")), isTelemetryEnabled && span.setStatus({ code: 2, message: "No active changeset" });
542
572
  return;
@@ -549,7 +579,7 @@ async function changesetCommitCommand(options) {
549
579
  name: changeset.name,
550
580
  changesetId: activeChangesetId,
551
581
  stagedChanges: 0
552
- }, { verbose: !0 }), isTelemetryEnabled && span.setStatus({ code: 0 });
582
+ }, { verbose: !0 }), await restore(), isTelemetryEnabled && span.setStatus({ code: 0 });
553
583
  return;
554
584
  }
555
585
  isJson() || (console.log(ansis.bold(`
@@ -567,21 +597,26 @@ Committing changeset: ${ansis.cyan(changeset.name)}`)), console.log(ansis.dim(`S
567
597
  stagedChanges: changeCount,
568
598
  validationPassed: result.validation.passed
569
599
  };
570
- (result.skipped ?? 0) > 0 && (commitDetails.skipped = result.skipped, commitDetails.skippedDetails = (result.skippedDetails ?? []).slice(0, 10)), result.failed > 0 && (commitDetails.failed = result.failed);
600
+ reportCommitValidation(result, commitDetails), (result.skipped ?? 0) > 0 && (commitDetails.skipped = result.skipped, commitDetails.skippedDetails = (result.skippedDetails ?? []).slice(0, 10)), result.failed > 0 && (commitDetails.failed = result.failed);
571
601
  const accountedFor = result.committed + (result.skipped ?? 0) + result.failed;
572
602
  if (accountedFor < changeCount) {
573
603
  const unaccounted = changeCount - accountedFor;
574
604
  commitDetails.unaccountedChanges = unaccounted, isJson() || console.log(ansis.yellow(`\u26A0 Warning: ${unaccounted} staged change(s) were not applied, skipped, or reported as failed. This is unexpected \u2014 check the changeset log for details.`));
575
605
  }
576
- result.driftWarning && (commitDetails.driftDetected = !0, isJson() || console.log(ansis.yellow("\u26A0 Warning: Model had drifted since changeset creation (--force was used)")), isTelemetryEnabled && span.setAttribute("commit.driftDetected", !0)), isTelemetryEnabled && span.setStatus({ code: 0 }), handleSuccess(`Committed ${result.committed} change(s)`, commitDetails, { verbose: !0 }), isJson() || console.log();
606
+ result.driftWarning && (commitDetails.driftDetected = !0, isJson() || console.log(ansis.yellow("\u26A0 Warning: Model had drifted since changeset creation (--force was used)")), isTelemetryEnabled && span.setAttribute("commit.driftDetected", !0)), isTelemetryEnabled && span.setStatus({ code: 0 }), handleSuccess(`Committed ${result.committed} change(s)`, commitDetails, { verbose: !0 }), await restore(), isJson() || console.log();
577
607
  } catch (error) {
578
608
  throw isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: `Commit failed and rolled back: ${getErrorMessage(error)}` })) : console.log(ansis.red(`\u2717 Commit failed and rolled back: ${getErrorMessage(error)}`)), isTelemetryEnabled && span.setAttribute("commit.rolledBack", !0), error;
579
609
  }
580
610
  } catch (error) {
581
- isTelemetryEnabled && (span.recordException(error), span.setStatus({
611
+ if (isTelemetryEnabled && (span.recordException(error), span.setStatus({
582
612
  code: 2,
583
613
  message: getErrorMessage(error)
584
- })), isJson() ? console.log(JSON.stringify({ status: "error", code: 1, message: getErrorMessage(error) })) : console.error(ansis.red(`Error: ${getErrorMessage(error)}`)), span.end(), process.exit(1);
614
+ })), isJson())
615
+ console.log(JSON.stringify({ status: "error", code: 1, message: getErrorMessage(error) }));
616
+ else if (console.error(ansis.red(`Error: ${getErrorMessage(error)}`)), error instanceof CLIError && error.suggestions?.length)
617
+ for (const suggestion of error.suggestions)
618
+ console.error(ansis.dim(` ${suggestion}`));
619
+ await restore().catch((restoreError) => console.error(ansis.red(`Error: could not reactivate the previous changeset: ${getErrorMessage(restoreError)}`))), span.end(), process.exit(1);
585
620
  }
586
621
  }, {
587
622
  "commit.validate": options?.validate !== !1,
@@ -594,7 +629,7 @@ async function changesetExportCommand(changesetId, options) {
594
629
  "export.format": format
595
630
  }) : null;
596
631
  try {
597
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !0 }), exporter = new ChangesetExporter(model.rootPath), ext = format === "patch" ? "patch" : format, outputPath = options.output || `${changesetId}.${ext}`, absolutePath = path.isAbsolute(outputPath) ? outputPath : path.join(process.cwd(), outputPath);
632
+ const model = await Model.load(options.model, { lazyLoad: !0 }), exporter = new ChangesetExporter(model.rootPath), ext = format === "patch" ? "patch" : format, outputPath = options.output || `${changesetId}.${ext}`, absolutePath = path.isAbsolute(outputPath) ? outputPath : path.join(process.cwd(), outputPath);
598
633
  isTelemetryEnabled && span && span.setAttribute("export.outputPath", outputPath), await exporter.exportToFile(changesetId, absolutePath, format), handleSuccess(`Exported changeset to ${outputPath}`, {
599
634
  changesetId,
600
635
  outputPath,
@@ -615,7 +650,7 @@ async function changesetImportCommand(file, options = {}) {
615
650
  "import.force": options.force === !0
616
651
  }) : null;
617
652
  try {
618
- const model = await Model.load(options.model || process.cwd(), { lazyLoad: !1 }), exporter = new ChangesetExporter(model.rootPath), absolutePath = path.isAbsolute(file) ? file : path.join(process.cwd(), file), imported = await exporter.importFromFile(absolutePath);
653
+ const model = await Model.load(options.model, { lazyLoad: !1 }), exporter = new ChangesetExporter(model.rootPath), absolutePath = path.isAbsolute(file) ? file : path.join(process.cwd(), file), imported = await exporter.importFromFile(absolutePath);
619
654
  isTelemetryEnabled && span && (span.setAttribute("changeset.name", imported.name), span.setAttribute("changeset.changeCount", imported.changes.length));
620
655
  const compatibility = await exporter.validateCompatibility(imported, model);
621
656
  if (isTelemetryEnabled && span && (span.setAttribute("import.compatible", compatibility.compatible), span.setAttribute("import.baseSnapshotMatch", compatibility.baseSnapshotMatch)), !compatibility.compatible) {
@@ -734,12 +769,20 @@ Examples:
734
769
  $ dr changeset diff
735
770
  $ dr changeset diff --layer api`).action(async (options) => {
736
771
  await changesetDiffCommand(options);
737
- }), changesetGroup.command("commit").description("Apply staged changes to the base model").option("--model <path>", "Path to model root (contains model/manifest.yaml)").option("--validate", "Run validation before commit (default: true)", !0).option("--force", "Commit despite drift warnings", !1).addHelpText("after", `
772
+ }), changesetGroup.command("commit [changeset]").description("Apply a changeset's staged changes to the base model (the active one, or the one named)").allowExcessArguments(!1).option("--model <path>", "Path to model root (contains model/manifest.yaml)").addOption(new Option("--validate", "Run validation before commit (default)").hideHelp()).option("--no-validate", "Skip validation before commit (validation runs by default; only errors the changeset introduces block, errors already in the base model are reported as a count)").option("--force", "Commit despite drift warnings (does not skip validation)", !1).addHelpText("after", `
773
+ Validation compares the model with and without the changeset. Errors the
774
+ changeset introduces block the commit; errors the base model already had are
775
+ not counted against it, and the output says how many there were.
776
+
777
+ A named changeset (id or name) need not be active: it is activated for the
778
+ commit, and the changeset that was active before is active again afterwards.
779
+
738
780
  Examples:
739
781
  $ dr changeset commit
740
- $ dr changeset commit --validate
741
- $ dr changeset commit --force`).action(async (options) => {
742
- await changesetCommitCommand(options);
782
+ $ dr changeset commit add-order-api # commit the changeset named add-order-api
783
+ $ dr changeset commit --force # commit despite drift
784
+ $ dr changeset commit --no-validate # skip validation entirely`).action(async (name, options) => {
785
+ await changesetCommitCommand(name, options);
743
786
  }), changesetGroup.command("export <changeset-id>").description("Export changeset to portable file").option("--model <path>", "Path to model root (contains model/manifest.yaml)").option("-o, --output <file>", "Output file path").option("-f, --format <format>", "Export format (yaml|json|patch)", "yaml").addHelpText("after", `
744
787
  Examples:
745
788
  $ dr changeset export api-updates
@@ -753,6 +796,14 @@ Examples:
753
796
  $ dr changeset import ../team-changes.json
754
797
  $ dr changeset import changes.yaml --force`).action(async (file, options) => {
755
798
  await changesetImportCommand(file, options);
799
+ }), changesetGroup.command("verify [planned]").description("Compare a planned changeset with what was built (an as-built changeset, or the base model)").option("--model <path>", "Path to model root (contains model/manifest.yaml)").option("--against <changeset>", "As-built changeset (ID or name) to compare with").option("--base", "Compare with the base model").option("--extracted", "With --base: the as-built side landed from codebase_extract, so planned parts extraction can't observe are unverifiable, not missing").option("--no-match-by-source", "Do not match elements by shared source file").option("--json", "Output as JSON").addHelpText("after", `
800
+ The planned changeset defaults to the active one.
801
+
802
+ Examples:
803
+ $ dr changeset verify export-orders --against export-orders-as-built
804
+ $ dr changeset verify export-orders --base --json
805
+ $ dr changeset verify export-orders --base --extracted`).action(async (planned, options) => {
806
+ await changesetVerifyCommand(planned, options);
756
807
  }), changesetGroup.showSuggestionAfterError();
757
808
  }
758
809
  export {