@documentation-robotics/cli 0.1.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/README.md +74 -2
  2. package/dist/analysis/relationship-classifier.js +2 -9
  3. package/dist/analysis/relationship-classifier.js.map +2 -2
  4. package/dist/analyzers/call-graph-utils.js +2 -2
  5. package/dist/analyzers/call-graph-utils.js.map +2 -2
  6. package/dist/analyzers/cards/build.js +171 -0
  7. package/dist/analyzers/cards/build.js.map +7 -0
  8. package/dist/analyzers/cards/classify.js +42 -0
  9. package/dist/analyzers/cards/classify.js.map +7 -0
  10. package/dist/analyzers/cards/edge-index.js +44 -0
  11. package/dist/analyzers/cards/edge-index.js.map +7 -0
  12. package/dist/analyzers/cards/facts.js +46 -0
  13. package/dist/analyzers/cards/facts.js.map +7 -0
  14. package/dist/analyzers/cards/graph.js +42 -0
  15. package/dist/analyzers/cards/graph.js.map +7 -0
  16. package/dist/analyzers/cards/index.js +8 -0
  17. package/dist/analyzers/cards/index.js.map +7 -0
  18. package/dist/analyzers/cards/tier0.js +18 -0
  19. package/dist/analyzers/cards/tier0.js.map +7 -0
  20. package/dist/analyzers/cards/types.js +1 -0
  21. package/dist/analyzers/cards/types.js.map +7 -0
  22. package/dist/analyzers/cbm-analyzer.js +195 -171
  23. package/dist/analyzers/cbm-analyzer.js.map +2 -2
  24. package/dist/analyzers/cbm-responses.js +336 -0
  25. package/dist/analyzers/cbm-responses.js.map +7 -0
  26. package/dist/analyzers/edge-relationships.js +45 -0
  27. package/dist/analyzers/edge-relationships.js.map +7 -0
  28. package/dist/analyzers/mapping-loader.js +9 -0
  29. package/dist/analyzers/mapping-loader.js.map +2 -2
  30. package/dist/analyzers/tier0-rules.js +153 -0
  31. package/dist/analyzers/tier0-rules.js.map +7 -0
  32. package/dist/analyzers/types.js.map +1 -1
  33. package/dist/analyzers/verify-engine.js +22 -19
  34. package/dist/analyzers/verify-engine.js.map +2 -2
  35. package/dist/audit/relationships/ai/prompts.js +10 -10
  36. package/dist/audit/relationships/ai/prompts.js.map +2 -2
  37. package/dist/audit/relationships/analysis/layer-templates.js +52 -52
  38. package/dist/audit/relationships/analysis/layer-templates.js.map +1 -1
  39. package/dist/cli.js +112 -28
  40. package/dist/cli.js.map +3 -3
  41. package/dist/coding-agents/agents/claude-code.js +3 -1
  42. package/dist/coding-agents/agents/claude-code.js.map +2 -2
  43. package/dist/coding-agents/claude-code-client.js +2 -1
  44. package/dist/coding-agents/claude-code-client.js.map +2 -2
  45. package/dist/coding-agents/copilot-client.js +17 -12
  46. package/dist/coding-agents/copilot-client.js.map +2 -2
  47. package/dist/coding-agents/default-permissions.js +152 -0
  48. package/dist/coding-agents/default-permissions.js.map +7 -0
  49. package/dist/coding-agents/drbot-mcp.js +167 -0
  50. package/dist/coding-agents/drbot-mcp.js.map +7 -0
  51. package/dist/commands/add.js +12 -7
  52. package/dist/commands/add.js.map +2 -2
  53. package/dist/commands/analyzer.js +134 -23
  54. package/dist/commands/analyzer.js.map +2 -2
  55. package/dist/commands/audit.js +6 -6
  56. package/dist/commands/audit.js.map +2 -2
  57. package/dist/commands/changeset-verify.js +55 -0
  58. package/dist/commands/changeset-verify.js.map +7 -0
  59. package/dist/commands/changeset.js +261 -147
  60. package/dist/commands/changeset.js.map +2 -2
  61. package/dist/commands/delete.js +52 -19
  62. package/dist/commands/delete.js.map +3 -3
  63. package/dist/commands/element.js +3 -2
  64. package/dist/commands/element.js.map +2 -2
  65. package/dist/commands/farm.js +773 -0
  66. package/dist/commands/farm.js.map +7 -0
  67. package/dist/commands/init.js +11 -1
  68. package/dist/commands/init.js.map +2 -2
  69. package/dist/commands/mcp.js +122 -0
  70. package/dist/commands/mcp.js.map +7 -0
  71. package/dist/commands/relationship.js +251 -47
  72. package/dist/commands/relationship.js.map +2 -2
  73. package/dist/commands/reports.js +1 -1
  74. package/dist/commands/reports.js.map +2 -2
  75. package/dist/commands/update.js +56 -24
  76. package/dist/commands/update.js.map +2 -2
  77. package/dist/commands/upgrade.js +99 -11
  78. package/dist/commands/upgrade.js.map +3 -3
  79. package/dist/commands/validate.js +41 -3
  80. package/dist/commands/validate.js.map +2 -2
  81. package/dist/commands/version.js +2 -2
  82. package/dist/commands/version.js.map +2 -2
  83. package/dist/commands/visualize.js +4 -3
  84. package/dist/commands/visualize.js.map +2 -2
  85. package/dist/config.js +83 -0
  86. package/dist/config.js.map +7 -0
  87. package/dist/core/annotation-store.js +138 -0
  88. package/dist/core/annotation-store.js.map +7 -0
  89. package/dist/core/catalog-migration.js +33 -0
  90. package/dist/core/catalog-migration.js.map +7 -0
  91. package/dist/core/changeset-analysis.js +421 -0
  92. package/dist/core/changeset-analysis.js.map +7 -0
  93. package/dist/core/changeset-base-index.js +153 -0
  94. package/dist/core/changeset-base-index.js.map +7 -0
  95. package/dist/core/changeset-brief-delta.js +102 -0
  96. package/dist/core/changeset-brief-delta.js.map +7 -0
  97. package/dist/core/changeset-graph.js +281 -0
  98. package/dist/core/changeset-graph.js.map +7 -0
  99. package/dist/core/changeset-only-guard.js +32 -0
  100. package/dist/core/changeset-only-guard.js.map +7 -0
  101. package/dist/core/changeset-summary.js +68 -0
  102. package/dist/core/changeset-summary.js.map +7 -0
  103. package/dist/core/changeset-validator.js +66 -20
  104. package/dist/core/changeset-validator.js.map +2 -2
  105. package/dist/core/changeset-verify.js +518 -0
  106. package/dist/core/changeset-verify.js.map +7 -0
  107. package/dist/core/changeset.js +56 -9
  108. package/dist/core/changeset.js.map +2 -2
  109. package/dist/core/element-type-migration.js +145 -0
  110. package/dist/core/element-type-migration.js.map +7 -0
  111. package/dist/core/farm-manifest.js +140 -0
  112. package/dist/core/farm-manifest.js.map +7 -0
  113. package/dist/core/farm-sync-engine.js +346 -0
  114. package/dist/core/farm-sync-engine.js.map +7 -0
  115. package/dist/core/farm-sync-state.js +167 -0
  116. package/dist/core/farm-sync-state.js.map +7 -0
  117. package/dist/core/manifest.js +6 -3
  118. package/dist/core/manifest.js.map +2 -2
  119. package/dist/core/migration-registry.js +84 -1
  120. package/dist/core/migration-registry.js.map +2 -2
  121. package/dist/core/model-upgrade.js +102 -0
  122. package/dist/core/model-upgrade.js.map +7 -0
  123. package/dist/core/model.js +257 -44
  124. package/dist/core/model.js.map +3 -3
  125. package/dist/core/mutation-handler.js +71 -6
  126. package/dist/core/mutation-handler.js.map +2 -2
  127. package/dist/core/relationship-migration-table.js +6639 -0
  128. package/dist/core/relationship-migration-table.js.map +7 -0
  129. package/dist/core/relationship-migration.js +272 -0
  130. package/dist/core/relationship-migration.js.map +7 -0
  131. package/dist/core/relationship-prune.js +49 -0
  132. package/dist/core/relationship-prune.js.map +7 -0
  133. package/dist/core/relationship-staging.js +68 -0
  134. package/dist/core/relationship-staging.js.map +7 -0
  135. package/dist/core/relationships.js +26 -4
  136. package/dist/core/relationships.js.map +2 -2
  137. package/dist/core/report-data-model.js +7 -13
  138. package/dist/core/report-data-model.js.map +2 -2
  139. package/dist/core/staged-changeset-storage.js +64 -17
  140. package/dist/core/staged-changeset-storage.js.map +2 -2
  141. package/dist/core/staged-source-reference.js +28 -0
  142. package/dist/core/staged-source-reference.js.map +7 -0
  143. package/dist/core/staging-area.js +83 -18
  144. package/dist/core/staging-area.js.map +2 -2
  145. package/dist/core/virtual-projection.js +14 -5
  146. package/dist/core/virtual-projection.js.map +2 -2
  147. package/dist/export/archimate-exporter.js +1 -0
  148. package/dist/export/archimate-exporter.js.map +2 -2
  149. package/dist/generated/compiled-validators.js +2 -2
  150. package/dist/generated/compiled-validators.js.map +2 -2
  151. package/dist/generated/layer-registry.js +16 -16
  152. package/dist/generated/layer-registry.js.map +2 -2
  153. package/dist/generated/node-types.js +186 -168
  154. package/dist/generated/node-types.js.map +2 -2
  155. package/dist/generated/relationship-index.js +2209 -7727
  156. package/dist/generated/relationship-index.js.map +2 -2
  157. package/dist/integrations/claude_code/agents/dr-architect.md +16 -3
  158. package/dist/integrations/claude_code/agents/dr-extractor.md +1 -1
  159. package/dist/integrations/claude_code/commands/dr-analyzer.md +565 -0
  160. package/dist/integrations/claude_code/commands/dr-map.md +13 -0
  161. package/dist/integrations/claude_code/commands/dr-plan.md +40 -0
  162. package/dist/integrations/claude_code/commands/dr-relate.md +106 -96
  163. package/dist/integrations/claude_code/commands/dr-verify.md +45 -2
  164. package/dist/integrations/claude_code/docs/END_TO_END_WALKTHROUGH.md +14 -0
  165. package/dist/integrations/claude_code/docs/MCP_SERVER.md +79 -0
  166. package/dist/integrations/claude_code/docs/QUICK_START.md +37 -8
  167. package/dist/integrations/claude_code/docs/README.md +52 -1
  168. package/dist/integrations/claude_code/skills/dr_01_motivation_layer/SKILL.md +93 -72
  169. package/dist/integrations/claude_code/skills/dr_02_business_layer/SKILL.md +163 -126
  170. package/dist/integrations/claude_code/skills/dr_03_product_layer/SKILL.md +161 -126
  171. package/dist/integrations/claude_code/skills/dr_04_security_layer/SKILL.md +153 -133
  172. package/dist/integrations/claude_code/skills/dr_05_application_layer/SKILL.md +129 -100
  173. package/dist/integrations/claude_code/skills/dr_06_technology_layer/SKILL.md +111 -94
  174. package/dist/integrations/claude_code/skills/dr_07_api_layer/SKILL.md +143 -157
  175. package/dist/integrations/claude_code/skills/dr_08_data_model_layer/SKILL.md +117 -33
  176. package/dist/integrations/claude_code/skills/dr_09_dataset_layer/SKILL.md +74 -25
  177. package/dist/integrations/claude_code/skills/dr_10_ux_layer/SKILL.md +88 -12
  178. package/dist/integrations/claude_code/skills/dr_11_navigation_layer/SKILL.md +83 -24
  179. package/dist/integrations/claude_code/skills/dr_12_apm_layer/SKILL.md +57 -12
  180. package/dist/integrations/claude_code/skills/dr_13_testing_layer/SKILL.md +92 -15
  181. package/dist/integrations/claude_code/skills/dr_change_planning/SKILL.md +119 -0
  182. package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +3 -0
  183. package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +1 -1
  184. package/dist/integrations/github_copilot/agents/dr-architect.md +1 -1
  185. package/dist/integrations/github_copilot/skills/dr_01_motivation_layer/SKILL.md +182 -102
  186. package/dist/integrations/github_copilot/skills/dr_02_business_layer/SKILL.md +266 -148
  187. package/dist/integrations/github_copilot/skills/dr_03_product_layer/SKILL.md +547 -86
  188. package/dist/integrations/github_copilot/skills/dr_04_security_layer/SKILL.md +164 -169
  189. package/dist/integrations/github_copilot/skills/dr_05_application_layer/SKILL.md +420 -150
  190. package/dist/integrations/github_copilot/skills/dr_06_technology_layer/SKILL.md +331 -138
  191. package/dist/integrations/github_copilot/skills/dr_07_api_layer/SKILL.md +265 -201
  192. package/dist/integrations/github_copilot/skills/dr_08_data_model_layer/SKILL.md +181 -58
  193. package/dist/integrations/github_copilot/skills/dr_09_dataset_layer/SKILL.md +209 -57
  194. package/dist/integrations/github_copilot/skills/dr_10_ux_layer/SKILL.md +277 -112
  195. package/dist/integrations/github_copilot/skills/dr_11_navigation_layer/SKILL.md +219 -70
  196. package/dist/integrations/github_copilot/skills/dr_12_apm_layer/SKILL.md +189 -105
  197. package/dist/integrations/github_copilot/skills/dr_13_testing_layer/SKILL.md +222 -102
  198. package/dist/integrations/github_copilot/skills/dr_change_planning/SKILL.md +119 -0
  199. package/dist/integrations/github_copilot/skills/dr_changeset_reviewer/SKILL.md +3 -0
  200. package/dist/integrations/hash-utils.js.map +2 -2
  201. package/dist/mcp/api-key-manager.js +111 -0
  202. package/dist/mcp/api-key-manager.js.map +7 -0
  203. package/dist/mcp/changeset-only.js +34 -0
  204. package/dist/mcp/changeset-only.js.map +7 -0
  205. package/dist/mcp/http-transport.js +176 -0
  206. package/dist/mcp/http-transport.js.map +7 -0
  207. package/dist/mcp/resource-registry.js +97 -0
  208. package/dist/mcp/resource-registry.js.map +7 -0
  209. package/dist/mcp/tool-registry.js +60 -0
  210. package/dist/mcp/tool-registry.js.map +7 -0
  211. package/dist/mcp/tools/annotation-create.js +39 -0
  212. package/dist/mcp/tools/annotation-create.js.map +7 -0
  213. package/dist/mcp/tools/annotation-delete.js +29 -0
  214. package/dist/mcp/tools/annotation-delete.js.map +7 -0
  215. package/dist/mcp/tools/annotation-get.js +29 -0
  216. package/dist/mcp/tools/annotation-get.js.map +7 -0
  217. package/dist/mcp/tools/annotation-list.js +24 -0
  218. package/dist/mcp/tools/annotation-list.js.map +7 -0
  219. package/dist/mcp/tools/annotation-reply.js +34 -0
  220. package/dist/mcp/tools/annotation-reply.js.map +7 -0
  221. package/dist/mcp/tools/annotation-shared.js +10 -0
  222. package/dist/mcp/tools/annotation-shared.js.map +7 -0
  223. package/dist/mcp/tools/annotation-update.js +39 -0
  224. package/dist/mcp/tools/annotation-update.js.map +7 -0
  225. package/dist/mcp/tools/changeset-analysis-tools.js +78 -0
  226. package/dist/mcp/tools/changeset-analysis-tools.js.map +7 -0
  227. package/dist/mcp/tools/changeset-editing.js +184 -0
  228. package/dist/mcp/tools/changeset-editing.js.map +7 -0
  229. package/dist/mcp/tools/changeset-lifecycle.js +83 -0
  230. package/dist/mcp/tools/changeset-lifecycle.js.map +7 -0
  231. package/dist/mcp/tools/changeset-list.js +33 -0
  232. package/dist/mcp/tools/changeset-list.js.map +7 -0
  233. package/dist/mcp/tools/changeset-shared.js +31 -0
  234. package/dist/mcp/tools/changeset-shared.js.map +7 -0
  235. package/dist/mcp/tools/changeset-show.js +55 -0
  236. package/dist/mcp/tools/changeset-show.js.map +7 -0
  237. package/dist/mcp/tools/changeset-verify.js +43 -0
  238. package/dist/mcp/tools/changeset-verify.js.map +7 -0
  239. package/dist/mcp/tools/chat-launch.js +50 -0
  240. package/dist/mcp/tools/chat-launch.js.map +7 -0
  241. package/dist/mcp/tools/chat-status.js +26 -0
  242. package/dist/mcp/tools/chat-status.js.map +7 -0
  243. package/dist/mcp/tools/index.js +65 -0
  244. package/dist/mcp/tools/index.js.map +7 -0
  245. package/dist/mcp/tools/model-add.js +107 -0
  246. package/dist/mcp/tools/model-add.js.map +7 -0
  247. package/dist/mcp/tools/model-delete.js +99 -0
  248. package/dist/mcp/tools/model-delete.js.map +7 -0
  249. package/dist/mcp/tools/model-export.js +72 -0
  250. package/dist/mcp/tools/model-export.js.map +7 -0
  251. package/dist/mcp/tools/model-info.js +51 -0
  252. package/dist/mcp/tools/model-info.js.map +7 -0
  253. package/dist/mcp/tools/model-list.js +53 -0
  254. package/dist/mcp/tools/model-list.js.map +7 -0
  255. package/dist/mcp/tools/model-reload.js +34 -0
  256. package/dist/mcp/tools/model-reload.js.map +7 -0
  257. package/dist/mcp/tools/model-search.js +102 -0
  258. package/dist/mcp/tools/model-search.js.map +7 -0
  259. package/dist/mcp/tools/model-show.js +68 -0
  260. package/dist/mcp/tools/model-show.js.map +7 -0
  261. package/dist/mcp/tools/model-stats.js +22 -0
  262. package/dist/mcp/tools/model-stats.js.map +7 -0
  263. package/dist/mcp/tools/model-trace.js +118 -0
  264. package/dist/mcp/tools/model-trace.js.map +7 -0
  265. package/dist/mcp/tools/model-update.js +121 -0
  266. package/dist/mcp/tools/model-update.js.map +7 -0
  267. package/dist/mcp/tools/model-validate.js +78 -0
  268. package/dist/mcp/tools/model-validate.js.map +7 -0
  269. package/dist/mcp/tools/relationship-tools.js +98 -0
  270. package/dist/mcp/tools/relationship-tools.js.map +7 -0
  271. package/dist/mcp/tools/shared.js +126 -0
  272. package/dist/mcp/tools/shared.js.map +7 -0
  273. package/dist/mcp/tools/spec-type.js +90 -0
  274. package/dist/mcp/tools/spec-type.js.map +7 -0
  275. package/dist/reports/model-layer-report-generator.js +5 -3
  276. package/dist/reports/model-layer-report-generator.js.map +2 -2
  277. package/dist/reports/model-readme-generator.js +116 -0
  278. package/dist/reports/model-readme-generator.js.map +7 -0
  279. package/dist/reports/model-report-data.js +37 -1
  280. package/dist/reports/model-report-data.js.map +2 -2
  281. package/dist/reports/model-report-orchestrator.js +29 -6
  282. package/dist/reports/model-report-orchestrator.js.map +2 -2
  283. package/dist/reports/model-report-utils.js +9 -0
  284. package/dist/reports/model-report-utils.js.map +7 -0
  285. package/dist/schemas/bundled/analyzers/cbm.json +1186 -68
  286. package/dist/schemas/bundled/analyzers/manifest.json +2 -2
  287. package/dist/schemas/bundled/api.json +1029 -1658
  288. package/dist/schemas/bundled/apm.json +499 -734
  289. package/dist/schemas/bundled/application.json +745 -370
  290. package/dist/schemas/bundled/base.json +3 -220
  291. package/dist/schemas/bundled/business.json +452 -366
  292. package/dist/schemas/bundled/data-model.json +403 -383
  293. package/dist/schemas/bundled/data-store.json +334 -558
  294. package/dist/schemas/bundled/manifest.json +18 -18
  295. package/dist/schemas/bundled/motivation.json +349 -368
  296. package/dist/schemas/bundled/navigation.json +415 -731
  297. package/dist/schemas/bundled/product.json +325 -159
  298. package/dist/schemas/bundled/security.json +864 -1232
  299. package/dist/schemas/bundled/technology.json +574 -703
  300. package/dist/schemas/bundled/testing.json +718 -1643
  301. package/dist/schemas/bundled/ux.json +739 -1352
  302. package/dist/server/schemas.js +8 -0
  303. package/dist/server/schemas.js.map +2 -2
  304. package/dist/server/server.js +234 -31
  305. package/dist/server/server.js.map +2 -2
  306. package/dist/server-entry.js +2 -1
  307. package/dist/server-entry.js.map +2 -2
  308. package/dist/telemetry/config.js +2 -40
  309. package/dist/telemetry/config.js.map +2 -2
  310. package/dist/telemetry/index.js +1 -1
  311. package/dist/types/index.js.map +2 -2
  312. package/dist/utils/ansi-suppressor.js +23 -0
  313. package/dist/utils/ansi-suppressor.js.map +7 -0
  314. package/dist/utils/attribute-patch.js +41 -0
  315. package/dist/utils/attribute-patch.js.map +7 -0
  316. package/dist/utils/color-utils.js +34 -0
  317. package/dist/utils/color-utils.js.map +7 -0
  318. package/dist/utils/element-reference-shape.js +15 -1
  319. package/dist/utils/element-reference-shape.js.map +3 -3
  320. package/dist/utils/error-hints.js +29 -0
  321. package/dist/utils/error-hints.js.map +7 -0
  322. package/dist/utils/errors.js +75 -10
  323. package/dist/utils/errors.js.map +2 -2
  324. package/dist/utils/globals.js +17 -1
  325. package/dist/utils/globals.js.map +2 -2
  326. package/dist/utils/project-paths.js +50 -3
  327. package/dist/utils/project-paths.js.map +2 -2
  328. package/dist/utils/reference-path-parser.js +49 -0
  329. package/dist/utils/reference-path-parser.js.map +7 -0
  330. package/dist/utils/source-reference.js +17 -10
  331. package/dist/utils/source-reference.js.map +2 -2
  332. package/dist/utils/spec-version.js +10 -2
  333. package/dist/utils/spec-version.js.map +2 -2
  334. package/dist/validators/composed-reference-validator.js +240 -0
  335. package/dist/validators/composed-reference-validator.js.map +7 -0
  336. package/dist/validators/reference-validator.js +57 -13
  337. package/dist/validators/reference-validator.js.map +3 -3
  338. package/dist/validators/relationship-schema-validator.js +33 -5
  339. package/dist/validators/relationship-schema-validator.js.map +3 -3
  340. package/dist/validators/schema-validator.js +27 -9
  341. package/dist/validators/schema-validator.js.map +2 -2
  342. package/dist/validators/types.js.map +1 -1
  343. package/dist/viewer/README.md +6 -6
  344. package/dist/viewer/assets/main-CxzcuU_o.js +84 -0
  345. package/dist/viewer/assets/main-j-7ULYpm.css +1 -0
  346. package/dist/viewer/index.html +2 -2
  347. package/dist/viewer/manifest.json +10 -10
  348. package/dist/viewer/version.json +1 -1
  349. package/package.json +7 -3
  350. package/dist/viewer/assets/main-B7AOQXXX.js +0 -81
  351. package/dist/viewer/assets/main-vdrFrG7q.css +0 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/core/mutation-handler.ts"],
4
- "sourcesContent": ["/**\n * MutationHandler - Unified mutation execution strategy\n *\n * Eliminates duplicate code paths by centralizing all element mutations.\n * Ensures consistency between staging and base model operations through\n * a single execution path that supports both.\n *\n * This fixes data corruption risk from divergent code paths in add/update/delete commands.\n */\n\nimport { Model } from \"./model.js\";\nimport { Element } from \"./element.js\";\nimport { StagingAreaManager } from \"./staging-area.js\";\nimport { isValidLayerName } from \"./layers.js\";\nimport { CLIError } from \"../utils/errors.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { ModelReportOrchestrator } from \"../reports/model-report-orchestrator.js\";\nimport { emitLog, SeverityNumber } from \"../telemetry/index.js\";\n\nexport type MutationType = \"add\" | \"update\" | \"delete\";\n\nexport interface MutationContext {\n model: Model;\n elementId: string;\n layerName: string;\n element?: Element;\n before?: Record<string, unknown>;\n after?: Record<string, unknown>;\n}\n\nexport interface MutationStep {\n execute: (context: MutationContext) => void | Promise<void>;\n stageable: boolean; // Can this step be executed in staging?\n description: string;\n}\n\n/**\n * Unified mutation executor\n *\n * Single point of mutation execution that:\n * 1. Builds complete before/after states\n * 2. Validates mutations\n * 3. Executes consistently for both staging and base model\n * 4. Handles all persistence atomically\n * 5. Tracks changes in legacy changeset context\n */\nexport class MutationHandler {\n private context: MutationContext;\n private steps: MutationStep[] = [];\n private stagingManager: StagingAreaManager;\n\n constructor(model: Model, elementId: string, layerName: string) {\n this.context = { model, elementId, layerName };\n this.stagingManager = new StagingAreaManager(model.rootPath, model);\n }\n\n /**\n * Set the element being mutated\n */\n setElement(element: Element): this {\n this.context.element = element;\n return this;\n }\n\n /**\n * Add a mutation step\n */\n addStep(step: MutationStep): this {\n this.steps.push(step);\n return this;\n }\n\n /**\n * Get before state (snapshot before mutations)\n */\n getBeforeState(): Record<string, unknown> | undefined {\n return this.context.before;\n }\n\n /**\n * Get after state (result of mutations)\n */\n getAfterState(): Record<string, unknown> | undefined {\n return this.context.after;\n }\n\n /**\n * Get staging manager for accessing changeset information\n */\n getStagingManager(): StagingAreaManager {\n return this.stagingManager;\n }\n\n /**\n * Compute before and after states\n *\n * For add: before is undefined, after is the new element state\n * For update: before is original state, after is modified state\n * For delete: before is original state, after is undefined\n */\n async computeStates(element: Element): Promise<void> {\n this.context.element = element;\n this.context.before = element.toJSON() as unknown as Record<string, unknown>;\n this.context.after = { ...this.context.before };\n }\n\n /**\n * Execute mutation for add operation\n */\n async executeAdd(\n element: Element,\n mutator: (elem: Element) => void | Promise<void>\n ): Promise<void> {\n // For add, before is undefined, after is the new element\n this.context.element = element;\n this.context.before = undefined;\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: capture after state and stage\n this.context.after = element.toJSON() as unknown as Record<string, unknown>;\n\n await this.stagingManager.stage(activeChangeset.id, {\n type: \"add\",\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n after: this.context.after,\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n // Base model path: add element and persist\n await mutator(element);\n this.context.after = element.toJSON() as unknown as Record<string, unknown>;\n\n // Persist to base model\n await this._persistChanges(\"add\");\n }\n\n /**\n * Execute mutation for update operation\n */\n async executeUpdate(\n element: Element,\n mutator: (elem: Element, after: Record<string, unknown>) => Promise<void>\n ): Promise<void> {\n // Compute before and after states\n this.context.element = element;\n this.context.before = element.toJSON() as unknown as Record<string, unknown>;\n this.context.after = { ...this.context.before };\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: apply mutations to after state, then stage\n await mutator(element, this.context.after);\n\n await this.stagingManager.stage(activeChangeset.id, {\n type: \"update\",\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n before: this.context.before,\n after: this.context.after,\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n // Base model path: apply mutations atomically\n await this._executeBasePath(mutator);\n }\n\n /**\n * Execute mutation for delete operation\n */\n async executeDelete(element: Element): Promise<void> {\n // For delete, before is the current state, after is undefined\n this.context.element = element;\n this.context.before = element.toJSON() as unknown as Record<string, unknown>;\n this.context.after = undefined;\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: stage the deletion only\n await this.stagingManager.stage(activeChangeset.id, {\n type: \"delete\",\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n before: this.context.before,\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n // Base model path: delete from model\n const layer = (await this.context.model.getLayer(this.context.layerName))!;\n const deleted = layer.deleteElement(element.path || element.id);\n\n if (!deleted) {\n throw new CLIError(`Failed to delete element ${this.context.elementId}`, 1, [\n \"Element may have already been deleted\",\n ]);\n }\n\n // Delete relationships\n this.context.model.relationships.deleteForElement(this.context.elementId);\n\n // Track and save atomically\n await this._persistChanges(\"delete\");\n }\n\n /**\n * Execute all registered steps and persist\n */\n async execute(\n mutator: (elem: Element, after: Record<string, unknown>) => Promise<void>,\n type: \"add\" | \"update\" | \"delete\"\n ): Promise<void> {\n if (!this.context.element) {\n throw new CLIError(\"Element not set on MutationHandler\", 1);\n }\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: build after state and stage\n if (this.context.before === undefined && type !== \"add\") {\n this.context.before = this.context.element.toJSON() as unknown as Record<string, unknown>;\n }\n\n this.context.after =\n type === \"delete\"\n ? undefined\n : {\n ...(this.context.before ||\n (this.context.element.toJSON() as unknown as Record<string, unknown>)),\n };\n\n if (type !== \"delete\" && this.context.after) {\n await mutator(this.context.element, this.context.after);\n }\n\n await this.stagingManager.stage(activeChangeset.id, {\n type,\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n ...(this.context.before !== undefined && { before: this.context.before }),\n ...(this.context.after !== undefined && { after: this.context.after }),\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n // Base model path: execute and persist atomically\n await this._executeBasePath(mutator, type);\n }\n\n /**\n * Base model path: execute mutations and persist atomically\n */\n private async _executeBasePath(\n mutator: (elem: Element, after: Record<string, unknown>) => Promise<void>,\n type?: string\n ): Promise<void> {\n if (!this.context.element) {\n throw new CLIError(\"Element not set\", 1);\n }\n\n // Initialize before state if not already set\n if (this.context.before === undefined) {\n this.context.before = this.context.element.toJSON() as unknown as Record<string, unknown>;\n }\n\n // Initialize after state if not already set\n if (this.context.after === undefined) {\n this.context.after = { ...this.context.before };\n }\n\n // Apply mutations to element AND after state together\n // This ensures they stay in sync\n await mutator(this.context.element, this.context.after);\n\n // Persist changes to disk\n await this._persistChanges(type);\n }\n\n /**\n * Persist changes to disk\n *\n * Performs sequential writes to layer, relationships, and manifest files.\n * If any write fails, subsequent writes are skipped via error propagation.\n * Note: Not truly atomic\u2014if a write succeeds then a later write fails,\n * earlier writes remain on disk. Use within transaction-like contexts only.\n */\n private async _persistChanges(type?: string): Promise<void> {\n try {\n // Save layer\n await this.context.model.saveLayer(this.context.layerName);\n\n // Save relationships if modified (for deletes)\n if (type === \"delete\" && this.context.model.relationships.isDirty()) {\n await this.context.model.saveRelationships();\n }\n\n // Save manifest\n await this.context.model.saveManifest();\n } catch (error) {\n throw new CLIError(\n `Failed to persist changes: ${getErrorMessage(error)}`,\n 1,\n [\"Check that the model directory is writable\", \"Verify the model is not corrupted\"]\n );\n }\n\n // Post-persist: regenerate affected layer reports (non-blocking, FR-4)\n // This is a separate try/catch from the above to ensure report failures never cause mutations to fail\n try {\n const orchestrator = new ModelReportOrchestrator(\n this.context.model,\n this.context.model.rootPath\n );\n if (isValidLayerName(this.context.layerName)) {\n const affected = orchestrator.computeAffectedLayers(this.context.layerName);\n await orchestrator.regenerate(affected);\n } else {\n emitLog(SeverityNumber.WARN, \"Report regeneration skipped: invalid layer name\", {\n \"layer.name\": this.context.layerName,\n \"elementId\": this.context.elementId,\n });\n }\n } catch (error) {\n emitLog(SeverityNumber.WARN, \"Failed to update layer reports after mutation\", {\n \"error\": getErrorMessage(error),\n \"layer.name\": this.context.layerName,\n \"elementId\": this.context.elementId,\n });\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * MutationHandler - Unified mutation execution strategy\n *\n * Eliminates duplicate code paths by centralizing all element mutations.\n * Ensures consistency between staging and base model operations through\n * a single execution path that supports both.\n *\n * This fixes data corruption risk from divergent code paths in add/update/delete commands.\n */\n\nimport { Model } from \"./model.js\";\nimport { Element } from \"./element.js\";\nimport { elementIdentifiers } from \"./relationships.js\";\nimport { StagingAreaManager } from \"./staging-area.js\";\nimport { isValidLayerName } from \"./layers.js\";\nimport { CLIError } from \"../utils/errors.js\";\nimport { ChangesetOnlyError } from \"./changeset-only-guard.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { ModelReportOrchestrator } from \"../reports/model-report-orchestrator.js\";\nimport { emitLog, SeverityNumber } from \"../telemetry/index.js\";\nimport type { Changeset, StagedChange } from \"./changeset.js\";\nimport { changedFields } from \"./changeset-summary.js\";\n\n/**\n * An element snapshot staged by an add, with an update applied: the top-level keys the update\n * changed (before vs after) take their new value, and a key the update cleared is removed. Keys the\n * update did not touch keep the add's own value, so the add's shape is preserved.\n */\nexport function foldIntoSnapshot(\n addAfter: Record<string, unknown>,\n before: Record<string, unknown> | undefined,\n after: Record<string, unknown> | undefined\n): Record<string, unknown> {\n const folded = { ...addAfter };\n const b = before ?? {};\n const a = after ?? {};\n for (const key of new Set([...Object.keys(b), ...Object.keys(a)])) {\n if (JSON.stringify(b[key]) === JSON.stringify(a[key])) continue;\n if (a[key] === undefined) {\n delete folded[key];\n } else {\n folded[key] = a[key];\n }\n }\n // A cleared source reference is written as `source_reference: null`; drop the legacy camelCase key\n // so it cannot shadow it.\n if (\"source_reference\" in a && JSON.stringify(b.source_reference) !== JSON.stringify(a.source_reference)) {\n delete folded.sourceReference;\n }\n return folded;\n}\n\nexport type MutationType = \"add\" | \"update\" | \"delete\";\n\nexport interface MutationContext {\n model: Model;\n elementId: string;\n layerName: string;\n element?: Element;\n before?: Record<string, unknown>;\n after?: Record<string, unknown>;\n}\n\nexport interface MutationStep {\n execute: (context: MutationContext) => void | Promise<void>;\n stageable: boolean; // Can this step be executed in staging?\n description: string;\n}\n\n/**\n * Unified mutation executor\n *\n * Single point of mutation execution that:\n * 1. Builds complete before/after states\n * 2. Validates mutations\n * 3. Executes consistently for both staging and base model\n * 4. Handles all persistence atomically\n * 5. Tracks changes in legacy changeset context\n */\nexport class MutationHandler {\n private context: MutationContext;\n private steps: MutationStep[] = [];\n private stagingManager: StagingAreaManager;\n private changedFields: string[] = [];\n private foldedIntoAdd = false;\n\n constructor(model: Model, elementId: string, layerName: string) {\n this.context = { model, elementId, layerName };\n this.stagingManager = new StagingAreaManager(model.rootPath, model);\n }\n\n /**\n * Set the element being mutated\n */\n setElement(element: Element): this {\n this.context.element = element;\n return this;\n }\n\n /**\n * Add a mutation step\n */\n addStep(step: MutationStep): this {\n this.steps.push(step);\n return this;\n }\n\n /**\n * Get before state (snapshot before mutations)\n */\n getBeforeState(): Record<string, unknown> | undefined {\n return this.context.before;\n }\n\n /**\n * Get after state (result of mutations)\n */\n getAfterState(): Record<string, unknown> | undefined {\n return this.context.after;\n }\n\n /**\n * Get staging manager for accessing changeset information\n */\n getStagingManager(): StagingAreaManager {\n return this.stagingManager;\n }\n\n /**\n * The fields the last executeUpdate changed (`attributes.x` for attribute keys), sorted.\n * Empty before an update runs or when it changed nothing.\n */\n getChangedFields(): string[] {\n return this.changedFields;\n }\n\n /** Whether the last executeUpdate rewrote the changeset's staged add of the element in place. */\n wasFoldedIntoAdd(): boolean {\n return this.foldedIntoAdd;\n }\n\n /**\n * The active changeset's add of this element, when an update should be folded into it: the\n * add is the element's only staged element change (an update staged after it by an earlier\n * build keeps the old append behaviour, so it is not overridden), and the base model does not\n * already hold the element (commit skips such an add; a staged update still applies).\n */\n private async stagedAddToFoldInto(changeset: Changeset, element: Element): Promise<StagedChange | null> {\n const ids = new Set(elementIdentifiers(element, this.context.elementId));\n const own = (changeset.changes as StagedChange[]).filter(\n (c) => !c.type.startsWith(\"relationship-\") && ids.has(c.elementId)\n );\n if (own.length !== 1 || own[0].type !== \"add\" || !own[0].after) return null;\n const baseLayer = await this.context.model.getBaseLayer(this.context.layerName);\n if ([...ids].some((id) => baseLayer?.getElement(id))) return null;\n return own[0];\n }\n\n /**\n * Compute before and after states\n *\n * For add: before is undefined, after is the new element state\n * For update: before is original state, after is modified state\n * For delete: before is original state, after is undefined\n */\n async computeStates(element: Element): Promise<void> {\n this.context.element = element;\n this.context.before = element.toJSON() as unknown as Record<string, unknown>;\n this.context.after = { ...this.context.before };\n }\n\n /**\n * Execute mutation for add operation\n */\n async executeAdd(\n element: Element,\n mutator: (elem: Element) => void | Promise<void>\n ): Promise<void> {\n // For add, before is undefined, after is the new element\n this.context.element = element;\n this.context.before = undefined;\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: capture after state and stage\n this.context.after = element.toJSON() as unknown as Record<string, unknown>;\n\n await this.stagingManager.stage(activeChangeset.id, {\n type: \"add\",\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n after: this.context.after,\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n // Base model path: add element and persist\n await mutator(element);\n this.context.after = element.toJSON() as unknown as Record<string, unknown>;\n\n // Persist to base model\n await this._persistChanges(\"add\");\n }\n\n /**\n * Execute mutation for update operation\n */\n async executeUpdate(\n element: Element,\n mutator: (elem: Element, after: Record<string, unknown>) => Promise<void>\n ): Promise<void> {\n // Compute before and after states\n this.context.element = element;\n this.context.before = element.toJSON() as unknown as Record<string, unknown>;\n this.context.after = { ...this.context.before };\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: apply mutations to after state, then stage\n await mutator(element, this.context.after);\n this.changedFields = changedFields(this.context.before, this.context.after);\n\n // An element this changeset adds: rewrite the add's snapshot rather than stacking an update.\n const add = await this.stagedAddToFoldInto(activeChangeset, element);\n if (add) {\n await this.stagingManager.restage(activeChangeset.id, add.elementId, {\n type: \"add\",\n elementId: add.elementId,\n layerName: add.layerName,\n ...(add.before !== undefined ? { before: add.before } : {}),\n after: foldIntoSnapshot(add.after!, this.context.before, this.context.after),\n timestamp: new Date().toISOString(),\n });\n this.foldedIntoAdd = true;\n return;\n }\n\n await this.stagingManager.stage(activeChangeset.id, {\n type: \"update\",\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n before: this.context.before,\n after: this.context.after,\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n // Base model path: apply mutations atomically\n await this._executeBasePath(mutator);\n }\n\n /**\n * Execute mutation for delete operation\n */\n async executeDelete(element: Element): Promise<void> {\n // For delete, before is the current state, after is undefined\n this.context.element = element;\n this.context.before = element.toJSON() as unknown as Record<string, unknown>;\n this.context.after = undefined;\n\n // Every identifier relationships.yaml may use for this element: UUID id, dotted\n // path, and whatever the caller addressed it by.\n const identifiers = elementIdentifiers(element, this.context.elementId);\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: stage the deletion, then stage the removal of every\n // relationship that names the element so the commit leaves no dangling rows\n // (and so commit validation does not reject the changeset for them).\n await this.stagingManager.stage(activeChangeset.id, {\n type: \"delete\",\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n before: this.context.before,\n timestamp: new Date().toISOString(),\n });\n\n const ids = new Set(identifiers);\n // A cascade delete stages one handler per element; a row between two deleted\n // elements must not be staged for removal twice.\n const alreadyStaged = new Set(\n activeChangeset.changes\n .filter((change) => change.type === \"relationship-delete\")\n .map((change) => change.elementId)\n );\n const dangling = this.context.model.relationships\n .getAll()\n .filter((rel) => ids.has(rel.source) || ids.has(rel.target))\n .filter((rel) => !alreadyStaged.has(`${rel.source}::${rel.predicate}::${rel.target}`));\n for (const rel of dangling) {\n alreadyStaged.add(`${rel.source}::${rel.predicate}::${rel.target}`);\n await this.stagingManager.stage(activeChangeset.id, {\n type: \"relationship-delete\",\n elementId: `${rel.source}::${rel.predicate}::${rel.target}`,\n layerName: rel.layer,\n before: {\n source: rel.source,\n target: rel.target,\n predicate: rel.predicate,\n layer: rel.layer,\n ...(rel.targetLayer ? { targetLayer: rel.targetLayer } : {}),\n ...(rel.properties ? { properties: rel.properties } : {}),\n },\n timestamp: new Date().toISOString(),\n });\n }\n return;\n }\n\n // Base model path: delete from model\n const layer = (await this.context.model.getLayer(this.context.layerName))!;\n const deleted = layer.deleteElement(element.path || element.id);\n\n if (!deleted) {\n throw new CLIError(`Failed to delete element ${this.context.elementId}`, 1, [\n \"Element may have already been deleted\",\n ]);\n }\n\n // Delete relationships that name the element by UUID or by path\n this.context.model.relationships.deleteForElement(identifiers);\n\n // Track and save atomically\n await this._persistChanges(\"delete\");\n }\n\n /**\n * Execute all registered steps and persist\n */\n async execute(\n mutator: (elem: Element, after: Record<string, unknown>) => Promise<void>,\n type: \"add\" | \"update\" | \"delete\"\n ): Promise<void> {\n if (!this.context.element) {\n throw new CLIError(\"Element not set on MutationHandler\", 1);\n }\n\n // Check if we're in staging mode\n const activeChangeset = await this.stagingManager.getActive();\n if (activeChangeset && activeChangeset.status === \"staged\") {\n // Staging path: build after state and stage\n if (this.context.before === undefined && type !== \"add\") {\n this.context.before = this.context.element.toJSON() as unknown as Record<string, unknown>;\n }\n\n this.context.after =\n type === \"delete\"\n ? undefined\n : {\n ...(this.context.before ||\n (this.context.element.toJSON() as unknown as Record<string, unknown>)),\n };\n\n if (type !== \"delete\" && this.context.after) {\n await mutator(this.context.element, this.context.after);\n }\n\n await this.stagingManager.stage(activeChangeset.id, {\n type,\n elementId: this.context.elementId,\n layerName: this.context.layerName,\n ...(this.context.before !== undefined && { before: this.context.before }),\n ...(this.context.after !== undefined && { after: this.context.after }),\n timestamp: new Date().toISOString(),\n });\n return;\n }\n\n // Base model path: execute and persist atomically\n await this._executeBasePath(mutator, type);\n }\n\n /**\n * Base model path: execute mutations and persist atomically\n */\n private async _executeBasePath(\n mutator: (elem: Element, after: Record<string, unknown>) => Promise<void>,\n type?: string\n ): Promise<void> {\n if (!this.context.element) {\n throw new CLIError(\"Element not set\", 1);\n }\n\n // Initialize before state if not already set\n if (this.context.before === undefined) {\n this.context.before = this.context.element.toJSON() as unknown as Record<string, unknown>;\n }\n\n // Initialize after state if not already set\n if (this.context.after === undefined) {\n this.context.after = { ...this.context.before };\n }\n\n // Apply mutations to element AND after state together\n // This ensures they stay in sync\n await mutator(this.context.element, this.context.after);\n this.changedFields = changedFields(this.context.before, this.context.after);\n\n // Persist changes to disk\n await this._persistChanges(type);\n }\n\n /**\n * Persist changes to disk\n *\n * Performs sequential writes to layer, relationships, and manifest files.\n * If any write fails, subsequent writes are skipped via error propagation.\n * Note: Not truly atomic\u2014if a write succeeds then a later write fails,\n * earlier writes remain on disk. Use within transaction-like contexts only.\n */\n private async _persistChanges(type?: string): Promise<void> {\n try {\n // Save layer\n await this.context.model.saveLayer(this.context.layerName);\n\n // Save relationships if modified (for deletes)\n if (type === \"delete\" && this.context.model.relationships.isDirty()) {\n await this.context.model.saveRelationships();\n }\n\n // Save manifest\n await this.context.model.saveManifest();\n } catch (error) {\n // A changeset-only refusal is not a disk failure: keep it recognisable for callers.\n if (error instanceof ChangesetOnlyError) throw error;\n throw new CLIError(\n `Failed to persist changes: ${getErrorMessage(error)}`,\n 1,\n [\"Check that the model directory is writable\", \"Verify the model is not corrupted\"]\n );\n }\n\n // Post-persist: regenerate affected layer reports (non-blocking, FR-4)\n // This is a separate try/catch from the above to ensure report failures never cause mutations to fail\n try {\n const orchestrator = new ModelReportOrchestrator(\n this.context.model,\n this.context.model.rootPath\n );\n if (isValidLayerName(this.context.layerName)) {\n const affected = orchestrator.computeAffectedLayers(this.context.layerName);\n await orchestrator.regenerate(affected);\n } else {\n emitLog(SeverityNumber.WARN, \"Report regeneration skipped: invalid layer name\", {\n \"layer.name\": this.context.layerName,\n \"elementId\": this.context.elementId,\n });\n }\n } catch (error) {\n emitLog(SeverityNumber.WARN, \"Failed to update layer reports after mutation\", {\n \"error\": getErrorMessage(error),\n \"layer.name\": this.context.layerName,\n \"elementId\": this.context.elementId,\n });\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }