@documentation-robotics/cli 0.1.0 → 0.1.7

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 (510) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +466 -693
  3. package/dist/analysis/data-model-analyzer.js +189 -0
  4. package/dist/analysis/data-model-analyzer.js.map +7 -0
  5. package/dist/analysis/index.js +3 -0
  6. package/dist/analysis/index.js.map +7 -0
  7. package/dist/analysis/relationship-classifier.js +181 -0
  8. package/dist/analysis/relationship-classifier.js.map +7 -0
  9. package/dist/analyzers/base-analyzer.js +1 -0
  10. package/dist/analyzers/base-analyzer.js.map +7 -0
  11. package/dist/analyzers/call-graph-utils.js +39 -0
  12. package/dist/analyzers/call-graph-utils.js.map +7 -0
  13. package/dist/analyzers/cbm-analyzer.js +1205 -0
  14. package/dist/analyzers/cbm-analyzer.js.map +7 -0
  15. package/dist/analyzers/heuristic-utils.js +55 -0
  16. package/dist/analyzers/heuristic-utils.js.map +7 -0
  17. package/dist/analyzers/mapping-loader.js +146 -0
  18. package/dist/analyzers/mapping-loader.js.map +7 -0
  19. package/dist/analyzers/registry.js +124 -0
  20. package/dist/analyzers/registry.js.map +7 -0
  21. package/dist/analyzers/session-state.js +176 -0
  22. package/dist/analyzers/session-state.js.map +7 -0
  23. package/dist/analyzers/stdio-client.js +208 -0
  24. package/dist/analyzers/stdio-client.js.map +7 -0
  25. package/dist/analyzers/types.js +15 -0
  26. package/dist/analyzers/types.js.map +7 -0
  27. package/dist/analyzers/verify-engine.js +209 -0
  28. package/dist/analyzers/verify-engine.js.map +7 -0
  29. package/dist/analyzers/verify-ignore.js +130 -0
  30. package/dist/analyzers/verify-ignore.js.map +7 -0
  31. package/dist/analyzers/version.js +8 -0
  32. package/dist/analyzers/version.js.map +7 -0
  33. package/dist/audit/ai/runner.js +41 -0
  34. package/dist/audit/ai/runner.js.map +7 -0
  35. package/dist/audit/differential-analyzer.js +183 -0
  36. package/dist/audit/differential-analyzer.js.map +7 -0
  37. package/dist/audit/index.js +32 -0
  38. package/dist/audit/index.js.map +7 -0
  39. package/dist/audit/nodes/ai/evaluator.js +49 -0
  40. package/dist/audit/nodes/ai/evaluator.js.map +7 -0
  41. package/dist/audit/nodes/ai/parser.js +55 -0
  42. package/dist/audit/nodes/ai/parser.js.map +7 -0
  43. package/dist/audit/nodes/ai/prompts.js +103 -0
  44. package/dist/audit/nodes/ai/prompts.js.map +7 -0
  45. package/dist/audit/nodes/analysis/node-completeness-checker.js +32 -0
  46. package/dist/audit/nodes/analysis/node-completeness-checker.js.map +7 -0
  47. package/dist/audit/nodes/analysis/node-definition-analyzer.js +47 -0
  48. package/dist/audit/nodes/analysis/node-definition-analyzer.js.map +7 -0
  49. package/dist/audit/nodes/analysis/node-overlap-detector.js +79 -0
  50. package/dist/audit/nodes/analysis/node-overlap-detector.js.map +7 -0
  51. package/dist/audit/nodes/model/orchestrator.js +82 -0
  52. package/dist/audit/nodes/model/orchestrator.js.map +7 -0
  53. package/dist/audit/nodes/spec/loader.js +116 -0
  54. package/dist/audit/nodes/spec/loader.js.map +7 -0
  55. package/dist/audit/nodes/spec/orchestrator.js +68 -0
  56. package/dist/audit/nodes/spec/orchestrator.js.map +7 -0
  57. package/dist/audit/nodes/types.js +1 -0
  58. package/dist/audit/nodes/types.js.map +7 -0
  59. package/dist/audit/pipeline/index.js +5 -0
  60. package/dist/audit/pipeline/index.js.map +7 -0
  61. package/dist/audit/pipeline/pipeline-orchestrator.js +218 -0
  62. package/dist/audit/pipeline/pipeline-orchestrator.js.map +7 -0
  63. package/dist/audit/relationships/ai/evaluator.js +235 -0
  64. package/dist/audit/relationships/ai/evaluator.js.map +7 -0
  65. package/dist/audit/relationships/ai/parser.js +197 -0
  66. package/dist/audit/relationships/ai/parser.js.map +7 -0
  67. package/dist/audit/relationships/ai/prompts.js +274 -0
  68. package/dist/audit/relationships/ai/prompts.js.map +7 -0
  69. package/dist/audit/relationships/analysis/balance-assessor.js +115 -0
  70. package/dist/audit/relationships/analysis/balance-assessor.js.map +7 -0
  71. package/dist/audit/relationships/analysis/coverage-analyzer.js +99 -0
  72. package/dist/audit/relationships/analysis/coverage-analyzer.js.map +7 -0
  73. package/dist/audit/relationships/analysis/duplicate-detector.js +95 -0
  74. package/dist/audit/relationships/analysis/duplicate-detector.js.map +7 -0
  75. package/dist/audit/relationships/analysis/gap-analyzer.js +99 -0
  76. package/dist/audit/relationships/analysis/gap-analyzer.js.map +7 -0
  77. package/dist/audit/relationships/analysis/layer-templates.js +294 -0
  78. package/dist/audit/relationships/analysis/layer-templates.js.map +7 -0
  79. package/dist/audit/relationships/graph/connectivity.js +129 -0
  80. package/dist/audit/relationships/graph/connectivity.js.map +7 -0
  81. package/dist/audit/relationships/graph/relationship-graph.js +179 -0
  82. package/dist/audit/relationships/graph/relationship-graph.js.map +7 -0
  83. package/dist/audit/relationships/model/balance-assessor.js +49 -0
  84. package/dist/audit/relationships/model/balance-assessor.js.map +7 -0
  85. package/dist/audit/relationships/model/coverage-analyzer.js +34 -0
  86. package/dist/audit/relationships/model/coverage-analyzer.js.map +7 -0
  87. package/dist/audit/relationships/model/duplicate-detector.js +68 -0
  88. package/dist/audit/relationships/model/duplicate-detector.js.map +7 -0
  89. package/dist/audit/relationships/model/gap-analyzer.js +41 -0
  90. package/dist/audit/relationships/model/gap-analyzer.js.map +7 -0
  91. package/dist/audit/relationships/model/orchestrator.js +126 -0
  92. package/dist/audit/relationships/model/orchestrator.js.map +7 -0
  93. package/dist/audit/relationships/spec/orchestrator.js +157 -0
  94. package/dist/audit/relationships/spec/orchestrator.js.map +7 -0
  95. package/dist/audit/reports/index.js +5 -0
  96. package/dist/audit/reports/index.js.map +7 -0
  97. package/dist/audit/reports/report-generator.js +118 -0
  98. package/dist/audit/reports/report-generator.js.map +7 -0
  99. package/dist/audit/snapshot-storage.js +163 -0
  100. package/dist/audit/snapshot-storage.js.map +7 -0
  101. package/dist/audit/types.js +21 -0
  102. package/dist/audit/types.js.map +7 -0
  103. package/dist/cli.js +223 -92
  104. package/dist/cli.js.map +3 -3
  105. package/dist/coding-agents/agents/claude-code.js +147 -0
  106. package/dist/coding-agents/agents/claude-code.js.map +7 -0
  107. package/dist/coding-agents/agents/index.js +5 -0
  108. package/dist/coding-agents/agents/index.js.map +7 -0
  109. package/dist/coding-agents/agents/types.js +1 -0
  110. package/dist/coding-agents/agents/types.js.map +7 -0
  111. package/dist/coding-agents/base-chat-client.js +45 -0
  112. package/dist/coding-agents/base-chat-client.js.map +7 -0
  113. package/dist/coding-agents/chat-utils.js +23 -0
  114. package/dist/coding-agents/chat-utils.js.map +7 -0
  115. package/dist/coding-agents/claude-code-client.js +246 -0
  116. package/dist/coding-agents/claude-code-client.js.map +7 -0
  117. package/dist/coding-agents/copilot-client.js +209 -0
  118. package/dist/coding-agents/copilot-client.js.map +7 -0
  119. package/dist/commands/add.js +95 -33
  120. package/dist/commands/add.js.map +2 -2
  121. package/dist/commands/analyzer.js +511 -0
  122. package/dist/commands/analyzer.js.map +7 -0
  123. package/dist/commands/audit-diff.js +49 -0
  124. package/dist/commands/audit-diff.js.map +7 -0
  125. package/dist/commands/audit-snapshots.js +62 -0
  126. package/dist/commands/audit-snapshots.js.map +7 -0
  127. package/dist/commands/audit.js +81 -0
  128. package/dist/commands/audit.js.map +7 -0
  129. package/dist/commands/catalog.js +248 -0
  130. package/dist/commands/catalog.js.map +7 -0
  131. package/dist/commands/changeset.js +577 -66
  132. package/dist/commands/changeset.js.map +2 -2
  133. package/dist/commands/chat.js +106 -83
  134. package/dist/commands/chat.js.map +2 -2
  135. package/dist/commands/claude.js +74 -0
  136. package/dist/commands/claude.js.map +7 -0
  137. package/dist/commands/conformance.js +71 -68
  138. package/dist/commands/conformance.js.map +2 -2
  139. package/dist/commands/copilot.js +75 -0
  140. package/dist/commands/copilot.js.map +7 -0
  141. package/dist/commands/delete.js +125 -11
  142. package/dist/commands/delete.js.map +3 -3
  143. package/dist/commands/discover-logic.js +44 -0
  144. package/dist/commands/discover-logic.js.map +7 -0
  145. package/dist/commands/docs.js +87 -0
  146. package/dist/commands/docs.js.map +7 -0
  147. package/dist/commands/element.js +14 -20
  148. package/dist/commands/element.js.map +2 -2
  149. package/dist/commands/export.js +13 -3
  150. package/dist/commands/export.js.map +2 -2
  151. package/dist/commands/import.js +51 -0
  152. package/dist/commands/import.js.map +7 -0
  153. package/dist/commands/info.js +30 -24
  154. package/dist/commands/info.js.map +2 -2
  155. package/dist/commands/init.js +27 -11
  156. package/dist/commands/init.js.map +2 -2
  157. package/dist/commands/list.js +63 -13
  158. package/dist/commands/list.js.map +3 -3
  159. package/dist/commands/relationship.js +225 -37
  160. package/dist/commands/relationship.js.map +2 -2
  161. package/dist/commands/report.js +54 -0
  162. package/dist/commands/report.js.map +7 -0
  163. package/dist/commands/reports.js +45 -0
  164. package/dist/commands/reports.js.map +7 -0
  165. package/dist/commands/schema.js +135 -0
  166. package/dist/commands/schema.js.map +7 -0
  167. package/dist/commands/search.js +40 -12
  168. package/dist/commands/search.js.map +2 -2
  169. package/dist/commands/show.js +58 -27
  170. package/dist/commands/show.js.map +2 -2
  171. package/dist/commands/stats.js +35 -0
  172. package/dist/commands/stats.js.map +7 -0
  173. package/dist/commands/trace.js +39 -16
  174. package/dist/commands/trace.js.map +2 -2
  175. package/dist/commands/update.js +141 -14
  176. package/dist/commands/update.js.map +2 -2
  177. package/dist/commands/upgrade.js +210 -46
  178. package/dist/commands/upgrade.js.map +3 -3
  179. package/dist/commands/validate.js +142 -23
  180. package/dist/commands/validate.js.map +3 -3
  181. package/dist/commands/version.js +8 -12
  182. package/dist/commands/version.js.map +2 -2
  183. package/dist/commands/visualize.js +162 -25
  184. package/dist/commands/visualize.js.map +2 -2
  185. package/dist/core/base-snapshot-manager.js +84 -0
  186. package/dist/core/base-snapshot-manager.js.map +7 -0
  187. package/dist/core/changeset-exporter.js +305 -0
  188. package/dist/core/changeset-exporter.js.map +7 -0
  189. package/dist/core/changeset-validator.js +41 -0
  190. package/dist/core/changeset-validator.js.map +7 -0
  191. package/dist/core/changeset.js +88 -173
  192. package/dist/core/changeset.js.map +2 -2
  193. package/dist/core/dependency-tracker.js +4 -2
  194. package/dist/core/dependency-tracker.js.map +2 -2
  195. package/dist/core/element.js +98 -27
  196. package/dist/core/element.js.map +2 -2
  197. package/dist/core/golden-copy-cache.js +290 -0
  198. package/dist/core/golden-copy-cache.js.map +7 -0
  199. package/dist/core/graph-model.js +266 -0
  200. package/dist/core/graph-model.js.map +7 -0
  201. package/dist/core/layer.js +159 -16
  202. package/dist/core/layer.js.map +2 -2
  203. package/dist/core/layers.js +32 -0
  204. package/dist/core/layers.js.map +7 -0
  205. package/dist/core/manifest.js +32 -11
  206. package/dist/core/manifest.js.map +2 -2
  207. package/dist/core/migration-registry.js +56 -1
  208. package/dist/core/migration-registry.js.map +2 -2
  209. package/dist/core/model.js +424 -217
  210. package/dist/core/model.js.map +3 -3
  211. package/dist/core/mutation-handler.js +179 -0
  212. package/dist/core/mutation-handler.js.map +7 -0
  213. package/dist/core/reference-registry.js +29 -21
  214. package/dist/core/reference-registry.js.map +2 -2
  215. package/dist/core/relationship-catalog.js +189 -0
  216. package/dist/core/relationship-catalog.js.map +7 -0
  217. package/dist/core/relationship-registry.js.map +2 -2
  218. package/dist/core/relationships.js.map +1 -1
  219. package/dist/core/report-data-model.js +285 -0
  220. package/dist/core/report-data-model.js.map +7 -0
  221. package/dist/core/spec-data-service.js +185 -0
  222. package/dist/core/spec-data-service.js.map +7 -0
  223. package/dist/core/spec-loader-types.js +1 -0
  224. package/dist/core/spec-loader-types.js.map +7 -0
  225. package/dist/core/spec-loader.js +234 -0
  226. package/dist/core/spec-loader.js.map +7 -0
  227. package/dist/core/staged-changeset-storage.js +282 -0
  228. package/dist/core/staged-changeset-storage.js.map +7 -0
  229. package/dist/core/staging-area.js +1002 -0
  230. package/dist/core/staging-area.js.map +7 -0
  231. package/dist/core/stats-collector.js +169 -0
  232. package/dist/core/stats-collector.js.map +7 -0
  233. package/dist/core/virtual-projection.js +443 -0
  234. package/dist/core/virtual-projection.js.map +7 -0
  235. package/dist/export/archimate-exporter.js +99 -60
  236. package/dist/export/archimate-exporter.js.map +2 -2
  237. package/dist/export/audit-formatters.js +479 -0
  238. package/dist/export/audit-formatters.js.map +7 -0
  239. package/dist/export/diff-formatters.js +99 -0
  240. package/dist/export/diff-formatters.js.map +7 -0
  241. package/dist/export/export-manager.js.map +2 -2
  242. package/dist/export/graphml-exporter.js +44 -27
  243. package/dist/export/graphml-exporter.js.map +2 -2
  244. package/dist/export/index.js +4 -0
  245. package/dist/export/index.js.map +2 -2
  246. package/dist/export/json-schema-exporter.js +55 -42
  247. package/dist/export/json-schema-exporter.js.map +2 -2
  248. package/dist/export/markdown-exporter.js +92 -70
  249. package/dist/export/markdown-exporter.js.map +2 -2
  250. package/dist/export/markdown-generator.js +248 -0
  251. package/dist/export/markdown-generator.js.map +7 -0
  252. package/dist/export/markdown-utils.js +30 -0
  253. package/dist/export/markdown-utils.js.map +7 -0
  254. package/dist/export/mermaid-markdown-exporter.js +37 -0
  255. package/dist/export/mermaid-markdown-exporter.js.map +7 -0
  256. package/dist/export/openapi-exporter.js +119 -71
  257. package/dist/export/openapi-exporter.js.map +2 -2
  258. package/dist/export/plantuml-exporter.js +104 -39
  259. package/dist/export/plantuml-exporter.js.map +2 -2
  260. package/dist/export/report-formatters.js +111 -0
  261. package/dist/export/report-formatters.js.map +7 -0
  262. package/dist/export/stats-formatters.js +98 -0
  263. package/dist/export/stats-formatters.js.map +7 -0
  264. package/dist/export/types.js +2 -14
  265. package/dist/export/types.js.map +2 -2
  266. package/dist/export/verify-formatters.js +153 -0
  267. package/dist/export/verify-formatters.js.map +7 -0
  268. package/dist/generated/compiled-validators.js +17 -0
  269. package/dist/generated/compiled-validators.js.map +7 -0
  270. package/dist/generated/index.js +31 -0
  271. package/dist/generated/index.js.map +7 -0
  272. package/dist/generated/layer-registry.js +190 -0
  273. package/dist/generated/layer-registry.js.map +7 -0
  274. package/dist/generated/layer-types.js +7 -0
  275. package/dist/generated/layer-types.js.map +7 -0
  276. package/dist/generated/node-types.js +1719 -0
  277. package/dist/generated/node-types.js.map +7 -0
  278. package/dist/generated/relationship-index.js +14552 -0
  279. package/dist/generated/relationship-index.js.map +7 -0
  280. package/dist/import/archimate-importer.js +166 -0
  281. package/dist/import/archimate-importer.js.map +7 -0
  282. package/dist/import/index.js +47 -0
  283. package/dist/import/index.js.map +7 -0
  284. package/dist/import/openapi-importer.js +143 -0
  285. package/dist/import/openapi-importer.js.map +7 -0
  286. package/dist/import/types.js +1 -0
  287. package/dist/import/types.js.map +7 -0
  288. package/dist/integrations/base-manager.js +311 -0
  289. package/dist/integrations/base-manager.js.map +7 -0
  290. package/dist/integrations/claude-manager.js +360 -0
  291. package/dist/integrations/claude-manager.js.map +7 -0
  292. package/dist/integrations/claude_code/agents/dr-advisor.md +253 -0
  293. package/dist/integrations/claude_code/agents/dr-architect.md +278 -0
  294. package/dist/integrations/claude_code/agents/dr-extractor.md +286 -0
  295. package/dist/integrations/claude_code/commands/dr-changeset.md +657 -0
  296. package/dist/integrations/claude_code/commands/dr-design.md +373 -0
  297. package/dist/integrations/claude_code/commands/dr-info.md +132 -0
  298. package/dist/integrations/claude_code/commands/dr-init.md +251 -0
  299. package/dist/integrations/claude_code/commands/dr-map.md +936 -0
  300. package/dist/integrations/claude_code/commands/dr-model.md +493 -0
  301. package/dist/integrations/claude_code/commands/dr-relate.md +814 -0
  302. package/dist/integrations/claude_code/commands/dr-sync.md +279 -0
  303. package/dist/integrations/claude_code/commands/dr-validate.md +654 -0
  304. package/dist/integrations/claude_code/commands/dr-verify.md +559 -0
  305. package/dist/integrations/claude_code/docs/END_TO_END_WALKTHROUGH.md +903 -0
  306. package/dist/integrations/claude_code/docs/QUICK_START.md +271 -0
  307. package/dist/integrations/claude_code/docs/README.md +347 -0
  308. package/dist/integrations/claude_code/skills/dr_01_motivation_layer/SKILL.md +550 -0
  309. package/dist/integrations/claude_code/skills/dr_02_business_layer/SKILL.md +620 -0
  310. package/dist/integrations/claude_code/skills/dr_03_security_layer/SKILL.md +642 -0
  311. package/dist/integrations/claude_code/skills/dr_04_application_layer/SKILL.md +911 -0
  312. package/dist/integrations/claude_code/skills/dr_05_technology_layer/SKILL.md +836 -0
  313. package/dist/integrations/claude_code/skills/dr_06_api_layer/SKILL.md +933 -0
  314. package/dist/integrations/claude_code/skills/dr_07_data_model_layer/SKILL.md +210 -0
  315. package/dist/integrations/claude_code/skills/dr_08_dataset_layer/SKILL.md +319 -0
  316. package/dist/integrations/claude_code/skills/dr_09_ux_layer/SKILL.md +319 -0
  317. package/dist/integrations/claude_code/skills/dr_10_navigation_layer/SKILL.md +318 -0
  318. package/dist/integrations/claude_code/skills/dr_11_apm_layer/SKILL.md +273 -0
  319. package/dist/integrations/claude_code/skills/dr_12_testing_layer/SKILL.md +273 -0
  320. package/dist/integrations/claude_code/skills/dr_changeset_reviewer/SKILL.md +187 -0
  321. package/dist/integrations/claude_code/skills/dr_codebase_memory/SKILL.md +590 -0
  322. package/dist/integrations/claude_code/skills/dr_engineering_guide/SKILL.md +295 -0
  323. package/dist/integrations/copilot-manager.js +328 -0
  324. package/dist/integrations/copilot-manager.js.map +7 -0
  325. package/dist/integrations/github_copilot/agents/dr-advisor.md +243 -0
  326. package/dist/integrations/github_copilot/agents/dr-architect.md +1567 -0
  327. package/dist/integrations/github_copilot/skills/dr_01_motivation_layer/SKILL.md +491 -0
  328. package/dist/integrations/github_copilot/skills/dr_02_business_layer/SKILL.md +539 -0
  329. package/dist/integrations/github_copilot/skills/dr_03_security_layer/SKILL.md +667 -0
  330. package/dist/integrations/github_copilot/skills/dr_04_application_layer/SKILL.md +670 -0
  331. package/dist/integrations/github_copilot/skills/dr_05_technology_layer/SKILL.md +660 -0
  332. package/dist/integrations/github_copilot/skills/dr_06_api_layer/SKILL.md +855 -0
  333. package/dist/integrations/github_copilot/skills/dr_07_data_model_layer/SKILL.md +171 -0
  334. package/dist/integrations/github_copilot/skills/dr_08_dataset_layer/SKILL.md +216 -0
  335. package/dist/integrations/github_copilot/skills/dr_09_ux_layer/SKILL.md +230 -0
  336. package/dist/integrations/github_copilot/skills/dr_10_navigation_layer/SKILL.md +228 -0
  337. package/dist/integrations/github_copilot/skills/dr_11_apm_layer/SKILL.md +234 -0
  338. package/dist/integrations/github_copilot/skills/dr_12_testing_layer/SKILL.md +230 -0
  339. package/dist/integrations/github_copilot/skills/dr_changeset_reviewer/SKILL.md +187 -0
  340. package/dist/integrations/hash-utils.js +51 -0
  341. package/dist/integrations/hash-utils.js.map +7 -0
  342. package/dist/integrations/types.js +16 -0
  343. package/dist/integrations/types.js.map +7 -0
  344. package/dist/reports/model-layer-report-generator.js +278 -0
  345. package/dist/reports/model-layer-report-generator.js.map +7 -0
  346. package/dist/reports/model-report-data.js +57 -0
  347. package/dist/reports/model-report-data.js.map +7 -0
  348. package/dist/reports/model-report-orchestrator.js +103 -0
  349. package/dist/reports/model-report-orchestrator.js.map +7 -0
  350. package/dist/schemas/bundled/analyzers/cbm.json +595 -0
  351. package/dist/schemas/bundled/analyzers/manifest.json +9 -0
  352. package/dist/schemas/bundled/api.json +3411 -0
  353. package/dist/schemas/bundled/apm.json +2371 -0
  354. package/dist/schemas/bundled/application.json +1253 -0
  355. package/dist/schemas/bundled/base.json +1622 -0
  356. package/dist/schemas/bundled/business.json +1279 -0
  357. package/dist/schemas/bundled/data-model.json +1298 -0
  358. package/dist/schemas/bundled/data-store.json +2025 -0
  359. package/dist/schemas/bundled/manifest.json +93 -0
  360. package/dist/schemas/bundled/motivation.json +1360 -0
  361. package/dist/schemas/bundled/navigation.json +1874 -0
  362. package/dist/schemas/bundled/security.json +3488 -0
  363. package/dist/schemas/bundled/technology.json +2067 -0
  364. package/dist/schemas/bundled/testing.json +3120 -0
  365. package/dist/schemas/bundled/ux.json +3592 -0
  366. package/dist/server/schemas.js +202 -0
  367. package/dist/server/schemas.js.map +7 -0
  368. package/dist/server/server.js +1336 -252
  369. package/dist/server/server.js.map +3 -3
  370. package/dist/server/telemetry-middleware.js +22 -15
  371. package/dist/server/telemetry-middleware.js.map +2 -2
  372. package/dist/server-entry.js +65 -0
  373. package/dist/server-entry.js.map +7 -0
  374. package/dist/telemetry/config.js +89 -0
  375. package/dist/telemetry/config.js.map +7 -0
  376. package/dist/telemetry/console-interceptor.js.map +1 -1
  377. package/dist/telemetry/detect.js +24 -0
  378. package/dist/telemetry/detect.js.map +7 -0
  379. package/dist/telemetry/fetch-otlp-exporter.js +112 -0
  380. package/dist/telemetry/fetch-otlp-exporter.js.map +7 -0
  381. package/dist/telemetry/index.js +153 -3
  382. package/dist/telemetry/index.js.map +2 -2
  383. package/dist/telemetry/resilient-exporter.js +22 -8
  384. package/dist/telemetry/resilient-exporter.js.map +2 -2
  385. package/dist/telemetry/resilient-log-exporter.js +17 -8
  386. package/dist/telemetry/resilient-log-exporter.js.map +2 -2
  387. package/dist/telemetry/test-instrumentation.js.map +2 -2
  388. package/dist/types/index.js +84 -0
  389. package/dist/types/index.js.map +3 -3
  390. package/dist/types/source-reference.js +1 -0
  391. package/dist/types/source-reference.js.map +7 -0
  392. package/dist/utils/chat-logger.js +292 -0
  393. package/dist/utils/chat-logger.js.map +7 -0
  394. package/dist/utils/claude-stream.js +8 -0
  395. package/dist/utils/claude-stream.js.map +7 -0
  396. package/dist/utils/date-utils.js +7 -0
  397. package/dist/utils/date-utils.js.map +7 -0
  398. package/dist/utils/element-utils.js.map +1 -1
  399. package/dist/utils/errors.js +88 -15
  400. package/dist/utils/errors.js.map +3 -3
  401. package/dist/utils/export-python-annotations.js +82 -0
  402. package/dist/utils/export-python-annotations.js.map +7 -0
  403. package/dist/utils/file-io.js +7 -2
  404. package/dist/utils/file-io.js.map +2 -2
  405. package/dist/utils/file-lock.js +156 -0
  406. package/dist/utils/file-lock.js.map +7 -0
  407. package/dist/utils/id-generator.js +18 -0
  408. package/dist/utils/id-generator.js.map +7 -0
  409. package/dist/utils/layer-name-formatter.js +16 -0
  410. package/dist/utils/layer-name-formatter.js.map +7 -0
  411. package/dist/utils/markdown-anchor.js +7 -0
  412. package/dist/utils/markdown-anchor.js.map +7 -0
  413. package/dist/utils/markdown-link.js +12 -0
  414. package/dist/utils/markdown-link.js.map +7 -0
  415. package/dist/utils/markdown-table.js +17 -0
  416. package/dist/utils/markdown-table.js.map +7 -0
  417. package/dist/utils/mermaid-utils.js +11 -0
  418. package/dist/utils/mermaid-utils.js.map +7 -0
  419. package/dist/utils/project-paths.js.map +2 -2
  420. package/dist/utils/source-reference.js +52 -0
  421. package/dist/utils/source-reference.js.map +7 -0
  422. package/dist/utils/spec-installer.js +40 -53
  423. package/dist/utils/spec-installer.js.map +2 -2
  424. package/dist/utils/spec-version.js +5 -1
  425. package/dist/utils/spec-version.js.map +2 -2
  426. package/dist/utils/string-utils.js +12 -0
  427. package/dist/utils/string-utils.js.map +7 -0
  428. package/dist/utils/table-formatting.js +19 -0
  429. package/dist/utils/table-formatting.js.map +7 -0
  430. package/dist/validators/index.js +4 -0
  431. package/dist/validators/index.js.map +2 -2
  432. package/dist/validators/naming-validator.js +20 -23
  433. package/dist/validators/naming-validator.js.map +2 -2
  434. package/dist/validators/reference-validator.js +23 -38
  435. package/dist/validators/reference-validator.js.map +2 -2
  436. package/dist/validators/relationship-schema-validator.js +243 -0
  437. package/dist/validators/relationship-schema-validator.js.map +7 -0
  438. package/dist/validators/schema-validator.js +168 -68
  439. package/dist/validators/schema-validator.js.map +2 -2
  440. package/dist/validators/semantic-validator.js +36 -60
  441. package/dist/validators/semantic-validator.js.map +2 -2
  442. package/dist/validators/types.js.map +2 -2
  443. package/dist/validators/validation-formatter.js +159 -0
  444. package/dist/validators/validation-formatter.js.map +7 -0
  445. package/dist/validators/validator.js +24 -38
  446. package/dist/validators/validator.js.map +2 -2
  447. package/dist/viewer/README.md +139 -0
  448. package/dist/viewer/assets/main-CY0Xufuj.css +1 -0
  449. package/dist/viewer/assets/main-DtgErnwF.js +81 -0
  450. package/dist/viewer/assets/vendor-CxKvDp2x.js +17 -0
  451. package/dist/viewer/favicon.svg +11 -0
  452. package/dist/viewer/fonts/inter/Inter-Black.woff2 +0 -0
  453. package/dist/viewer/fonts/inter/Inter-Bold.woff2 +0 -0
  454. package/dist/viewer/fonts/inter/Inter-ExtraBold.woff2 +0 -0
  455. package/dist/viewer/fonts/inter/Inter-Light.woff2 +0 -0
  456. package/dist/viewer/fonts/inter/Inter-Medium.woff2 +0 -0
  457. package/dist/viewer/fonts/inter/Inter-Regular.woff2 +0 -0
  458. package/dist/viewer/fonts/inter/Inter-SemiBold.woff2 +0 -0
  459. package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-Medium.woff2 +0 -0
  460. package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
  461. package/dist/viewer/fonts/jetbrains-mono/JetBrainsMono-SemiBold.woff2 +0 -0
  462. package/dist/viewer/index.html +15 -0
  463. package/dist/viewer/manifest.json +99 -0
  464. package/dist/viewer/version.json +1 -0
  465. package/package.json +42 -16
  466. package/PYTHON_CLI_PARITY.md +0 -265
  467. package/PYTHON_CLI_STRUCTURE_UPDATE.md +0 -246
  468. package/biome.json +0 -42
  469. package/bunfig.toml +0 -3
  470. package/dist/ai/claude-client.js +0 -71
  471. package/dist/ai/claude-client.js.map +0 -7
  472. package/dist/ai/context-provider.js +0 -129
  473. package/dist/ai/context-provider.js.map +0 -7
  474. package/dist/ai/tools.js +0 -231
  475. package/dist/ai/tools.js.map +0 -7
  476. package/dist/commands/migrate.js +0 -36
  477. package/dist/commands/migrate.js.map +0 -7
  478. package/dist/commands/project.js +0 -74
  479. package/dist/commands/project.js.map +0 -7
  480. package/dist/core/active-changeset.js +0 -52
  481. package/dist/core/active-changeset.js.map +0 -7
  482. package/dist/core/projection-engine.js +0 -288
  483. package/dist/core/projection-engine.js.map +0 -7
  484. package/dist/schemas/bundled/01-motivation-layer.schema.json +0 -942
  485. package/dist/schemas/bundled/02-business-layer.schema.json +0 -1293
  486. package/dist/schemas/bundled/03-security-layer.schema.json +0 -2177
  487. package/dist/schemas/bundled/04-application-layer.schema.json +0 -1328
  488. package/dist/schemas/bundled/05-technology-layer.schema.json +0 -1465
  489. package/dist/schemas/bundled/06-api-layer.schema.json +0 -1743
  490. package/dist/schemas/bundled/07-data-model-layer.schema.json +0 -1253
  491. package/dist/schemas/bundled/08-datastore-layer.schema.json +0 -892
  492. package/dist/schemas/bundled/09-ux-layer.schema.json +0 -1506
  493. package/dist/schemas/bundled/10-navigation-layer.schema.json +0 -843
  494. package/dist/schemas/bundled/11-apm-observability-layer.schema.json +0 -1430
  495. package/dist/schemas/bundled/12-testing-layer.schema.json +0 -1091
  496. package/dist/schemas/bundled/common/layer-extensions.schema.json +0 -266
  497. package/dist/schemas/bundled/common/predicates.schema.json +0 -493
  498. package/dist/schemas/bundled/common/relationships.schema.json +0 -791
  499. package/dist/schemas/bundled/common/source-references.schema.json +0 -71
  500. package/dist/schemas/bundled/link-registry.json +0 -1839
  501. package/dist/schemas/bundled/link-registry.schema.json +0 -339
  502. package/dist/schemas/bundled/relationship-catalog.json +0 -1302
  503. package/dist/schemas/bundled/relationship-type.schema.json +0 -221
  504. package/dist/utils/model-path.js +0 -22
  505. package/dist/utils/model-path.js.map +0 -7
  506. package/docs/TEST-INSTRUMENTATION.md +0 -405
  507. package/docs/telemetry.md +0 -427
  508. package/test-debug.js +0 -33
  509. package/test-special.mjs +0 -46
  510. package/test_runner.ts +0 -7
@@ -1,19 +1,45 @@
1
- import { readJSON, writeJSON, ensureDir, fileExists } from "../utils/file-io.js";
2
- import { Element } from "./element.js";
3
1
  class Changeset {
4
2
  name;
5
3
  description;
6
4
  created;
7
5
  modified;
8
6
  changes = [];
9
- status = "draft";
7
+ status = "staged";
8
+ // Staging workflow fields (required)
9
+ id;
10
+ baseSnapshot;
11
+ /**
12
+ * Get statistics derived from changes array.
13
+ * Computed on-demand to ensure always accurate regardless of how changes were added.
14
+ *
15
+ * @returns Statistics object with count of additions, modifications, deletions
16
+ */
17
+ get stats() {
18
+ const additions = this.changes.filter((c) => c.type === "add" || c.type === "relationship-add").length, modifications = this.changes.filter((c) => c.type === "update").length, deletions = this.changes.filter((c) => c.type === "delete" || c.type === "relationship-delete").length;
19
+ return { additions, modifications, deletions };
20
+ }
21
+ /**
22
+ * Create changeset from data object.
23
+ * Accepts only StagedChangesetData format with id and baseSnapshot.
24
+ *
25
+ * @param data - Changeset data from storage or API
26
+ */
10
27
  constructor(data) {
11
- this.name = data.name, this.description = data.description, this.created = data.created, this.modified = data.modified, this.changes = data.changes || [], this.status = data.status || "draft";
28
+ this.name = data.name, this.description = data.description, this.created = data.created, this.modified = data.modified, this.changes = (data.changes || []).map((change) => {
29
+ const { type, elementId, layerName, before, after, timestamp, sequenceNumber } = change, result = { type, elementId, layerName, before, after, timestamp };
30
+ return typeof sequenceNumber == "number" && (result.sequenceNumber = sequenceNumber), result;
31
+ }), this.status = data.status || "staged", this.id = data.id, this.baseSnapshot = data.baseSnapshot;
12
32
  }
13
33
  /**
14
- * Create a new changeset
34
+ * Create a new changeset with staged status.
35
+ *
36
+ * @param name - Human-readable name for the changeset
37
+ * @param description - Optional description of changes
38
+ * @param id - Unique changeset ID (required)
39
+ * @param baseSnapshot - SHA256 hash of base model at creation (required)
40
+ * @returns New Changeset instance in staged status
15
41
  */
16
- static create(name, description) {
42
+ static create(name, description, id, baseSnapshot) {
17
43
  const now = (/* @__PURE__ */ new Date()).toISOString();
18
44
  return new Changeset({
19
45
  name,
@@ -21,11 +47,21 @@ class Changeset {
21
47
  created: now,
22
48
  modified: now,
23
49
  changes: [],
24
- status: "draft"
50
+ status: "staged",
51
+ id,
52
+ baseSnapshot
25
53
  });
26
54
  }
27
55
  /**
28
- * Add a change to the changeset
56
+ * Add a change to the changeset.
57
+ * Records element mutation with before/after snapshots for audit purposes.
58
+ *
59
+ * @param type - Type of change (add, update, delete)
60
+ * @param elementId - ID of the element being changed
61
+ * @param layerName - Layer containing the element
62
+ * @param before - Element state before change (for update/delete operations)
63
+ * @param after - Element state after change (for add/update operations)
64
+ * @throws No exceptions; updates modified timestamp on success
29
65
  */
30
66
  addChange(type, elementId, layerName, before, after) {
31
67
  this.changes.push({
@@ -38,207 +74,86 @@ class Changeset {
38
74
  }), this.updateModified();
39
75
  }
40
76
  /**
41
- * Update the modified timestamp
77
+ * Update the modified timestamp to current time.
42
78
  */
43
79
  updateModified() {
44
80
  this.modified = (/* @__PURE__ */ new Date()).toISOString();
45
81
  }
46
82
  /**
47
- * Get number of changes
83
+ * Get the total number of changes in this changeset.
84
+ *
85
+ * @returns Number of changes (add + update + delete)
48
86
  */
49
87
  getChangeCount() {
50
88
  return this.changes.length;
51
89
  }
52
90
  /**
53
- * Get changes by type
91
+ * Get all changes of a specific type.
92
+ *
93
+ * @param type - Type of changes to filter for
94
+ * @returns Array of changes matching the type
54
95
  */
55
96
  getChangesByType(type) {
56
97
  return this.changes.filter((c) => c.type === type);
57
98
  }
58
99
  /**
59
- * Mark changeset as applied
100
+ * Mark changeset as staged.
101
+ * Enables the changeset to accept new changes via staging operations.
102
+ * Updates status and modified timestamp.
60
103
  */
61
- markApplied() {
62
- this.status = "applied", this.updateModified();
104
+ markStaged() {
105
+ this.status = "staged", this.updateModified();
63
106
  }
64
107
  /**
65
- * Mark changeset as reverted
108
+ * Mark changeset as committed.
109
+ * Indicates changes have been committed to the base model.
110
+ * Updates status and modified timestamp.
66
111
  */
67
- markReverted() {
68
- this.status = "reverted", this.updateModified();
112
+ markCommitted() {
113
+ this.status = "committed", this.updateModified();
69
114
  }
70
115
  /**
71
- * Serialize to JSON
116
+ * Mark changeset as discarded.
117
+ * Indicates changes have been discarded without committing.
118
+ * Updates status and modified timestamp.
119
+ */
120
+ markDiscarded() {
121
+ this.status = "discarded", this.updateModified();
122
+ }
123
+ /**
124
+ * Serialize changeset to JSON.
125
+ * Always returns StagedChangesetData format with sequenceNumbers added.
126
+ *
127
+ * @returns Serialized changeset data suitable for storage
72
128
  */
73
129
  toJSON() {
74
130
  return {
131
+ id: this.id,
75
132
  name: this.name,
76
133
  description: this.description,
77
134
  created: this.created,
78
135
  modified: this.modified,
79
- changes: this.changes,
80
- status: this.status
136
+ baseSnapshot: this.baseSnapshot,
137
+ status: this.status,
138
+ changes: this.changes.map((change, idx) => ({
139
+ ...change,
140
+ sequenceNumber: idx
141
+ })),
142
+ stats: this.stats
81
143
  };
82
144
  }
83
145
  /**
84
- * Create from JSON data
146
+ * Deserialize changeset from JSON data.
147
+ * Accepts StagedChangesetData format.
148
+ *
149
+ * @param data - Serialized changeset data
150
+ * @returns New Changeset instance
85
151
  */
86
152
  static fromJSON(data) {
87
153
  return new Changeset(data);
88
154
  }
89
155
  }
90
- class ChangesetManager {
91
- changesetsDir;
92
- constructor(modelPath) {
93
- this.changesetsDir = `${modelPath}/.dr/changesets`;
94
- }
95
- /**
96
- * Create a new changeset
97
- */
98
- async create(name, description) {
99
- const changeset = Changeset.create(name, description);
100
- return await this.save(changeset), changeset;
101
- }
102
- /**
103
- * Save a changeset to disk
104
- */
105
- async save(changeset) {
106
- await ensureDir(this.changesetsDir);
107
- const filePath = `${this.changesetsDir}/${this.sanitizeName(changeset.name)}.json`;
108
- await writeJSON(filePath, changeset.toJSON(), !0);
109
- }
110
- /**
111
- * Load a changeset by name
112
- */
113
- async load(name) {
114
- const filePath = `${this.changesetsDir}/${this.sanitizeName(name)}.json`;
115
- if (!await fileExists(filePath))
116
- return null;
117
- const data = await readJSON(filePath);
118
- return Changeset.fromJSON(data);
119
- }
120
- /**
121
- * List all changesets
122
- */
123
- async list() {
124
- if (!await fileExists(this.changesetsDir))
125
- return [];
126
- const files = await (await import("fs/promises")).readdir(this.changesetsDir), changesets = [];
127
- for (const file of files)
128
- if (file.endsWith(".json")) {
129
- const data = await readJSON(`${this.changesetsDir}/${file}`);
130
- changesets.push(Changeset.fromJSON(data));
131
- }
132
- return changesets;
133
- }
134
- /**
135
- * Delete a changeset
136
- */
137
- async delete(name) {
138
- const filePath = `${this.changesetsDir}/${this.sanitizeName(name)}.json`;
139
- if (!await fileExists(filePath))
140
- throw new Error(`Changeset '${name}' not found`);
141
- await (await import("fs/promises")).unlink(filePath);
142
- }
143
- /**
144
- * Apply a changeset to the model
145
- */
146
- async apply(model, name) {
147
- const changeset = await this.load(name);
148
- if (!changeset)
149
- throw new Error(`Changeset '${name}' not found`);
150
- const result = {
151
- changeset: name,
152
- applied: 0,
153
- failed: 0,
154
- errors: []
155
- };
156
- for (const change of changeset.changes)
157
- try {
158
- const layer = await model.getLayer(change.layerName);
159
- if (!layer)
160
- throw new Error(`Layer '${change.layerName}' not found`);
161
- if (change.type === "add" && change.after) {
162
- if (!layer.listElements().some((e) => e.id === change.elementId)) {
163
- const elementData = change.after, element = new Element({
164
- id: change.elementId,
165
- type: elementData.type || "unknown",
166
- name: elementData.name || change.elementId,
167
- description: elementData.description,
168
- properties: elementData
169
- });
170
- layer.addElement(element), result.applied++;
171
- }
172
- } else if (change.type === "update" && change.after) {
173
- const element = layer.getElement(change.elementId);
174
- if (element) {
175
- const elementData = change.after;
176
- Object.assign(element, elementData), result.applied++;
177
- }
178
- } else change.type === "delete" && layer.getElement(change.elementId) && (layer.deleteElement(change.elementId), result.applied++);
179
- } catch (error) {
180
- result.failed++, result.errors.push({
181
- change,
182
- error: error instanceof Error ? error.message : String(error)
183
- });
184
- }
185
- return result.failed === 0 && (changeset.markApplied(), await this.save(changeset)), result;
186
- }
187
- /**
188
- * Revert a changeset from the model
189
- */
190
- async revert(model, name) {
191
- const changeset = await this.load(name);
192
- if (!changeset)
193
- throw new Error(`Changeset '${name}' not found`);
194
- const result = {
195
- changeset: name,
196
- reverted: 0,
197
- failed: 0,
198
- errors: []
199
- };
200
- for (let i = changeset.changes.length - 1; i >= 0; i--) {
201
- const change = changeset.changes[i];
202
- try {
203
- const layer = await model.getLayer(change.layerName);
204
- if (!layer)
205
- throw new Error(`Layer '${change.layerName}' not found`);
206
- if (change.type === "add")
207
- layer.getElement(change.elementId) && (layer.deleteElement(change.elementId), result.reverted++);
208
- else if (change.type === "update" && change.before) {
209
- const element = layer.getElement(change.elementId);
210
- if (element) {
211
- const elementData = change.before;
212
- Object.assign(element, elementData), result.reverted++;
213
- }
214
- } else if (change.type === "delete" && change.before && !layer.listElements().some((e) => e.id === change.elementId)) {
215
- const elementData = change.before, element = new Element({
216
- id: change.elementId,
217
- type: elementData.type || "unknown",
218
- name: elementData.name || change.elementId,
219
- description: elementData.description,
220
- properties: elementData
221
- });
222
- layer.addElement(element), result.reverted++;
223
- }
224
- } catch (error) {
225
- result.failed++, result.errors.push({
226
- change,
227
- error: error instanceof Error ? error.message : String(error)
228
- });
229
- }
230
- }
231
- return result.failed === 0 && (changeset.markReverted(), await this.save(changeset)), result;
232
- }
233
- /**
234
- * Sanitize changeset name for use as filename
235
- */
236
- sanitizeName(name) {
237
- return name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
238
- }
239
- }
240
156
  export {
241
- Changeset,
242
- ChangesetManager
157
+ Changeset
243
158
  };
244
159
  //# sourceMappingURL=changeset.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/core/changeset.ts"],
4
- "sourcesContent": ["/**\n * Changeset - Represents a collection of model changes\n *\n * Changesets allow grouping related modifications to the architecture model\n * and applying/reverting them as a unit.\n */\n\nimport { readJSON, writeJSON, ensureDir, fileExists } from '../utils/file-io.js';\nimport type { Model } from './model.js';\nimport { Element } from './element.js';\n\n/**\n * Represents a single change in a changeset\n */\nexport interface Change {\n type: 'add' | 'update' | 'delete';\n elementId: string;\n layerName: string;\n before?: Record<string, unknown>;\n after?: Record<string, unknown>;\n timestamp: string;\n}\n\n/**\n * Changeset metadata\n */\nexport interface ChangesetData {\n name: string;\n description?: string;\n created: string;\n modified: string;\n changes: Change[];\n status: 'draft' | 'applied' | 'reverted';\n}\n\n/**\n * Changeset class for managing model changes\n */\nexport class Changeset {\n name: string;\n description?: string;\n created: string;\n modified: string;\n changes: Change[] = [];\n status: 'draft' | 'applied' | 'reverted' = 'draft';\n\n constructor(data: ChangesetData) {\n this.name = data.name;\n this.description = data.description;\n this.created = data.created;\n this.modified = data.modified;\n this.changes = data.changes || [];\n this.status = data.status || 'draft';\n }\n\n /**\n * Create a new changeset\n */\n static create(name: string, description?: string): Changeset {\n const now = new Date().toISOString();\n return new Changeset({\n name,\n description,\n created: now,\n modified: now,\n changes: [],\n status: 'draft',\n });\n }\n\n /**\n * Add a change to the changeset\n */\n addChange(\n type: 'add' | 'update' | 'delete',\n elementId: string,\n layerName: string,\n before?: Record<string, unknown>,\n after?: Record<string, unknown>\n ): void {\n this.changes.push({\n type,\n elementId,\n layerName,\n before,\n after,\n timestamp: new Date().toISOString(),\n });\n this.updateModified();\n }\n\n /**\n * Update the modified timestamp\n */\n updateModified(): void {\n this.modified = new Date().toISOString();\n }\n\n /**\n * Get number of changes\n */\n getChangeCount(): number {\n return this.changes.length;\n }\n\n /**\n * Get changes by type\n */\n getChangesByType(type: 'add' | 'update' | 'delete'): Change[] {\n return this.changes.filter((c) => c.type === type);\n }\n\n /**\n * Mark changeset as applied\n */\n markApplied(): void {\n this.status = 'applied';\n this.updateModified();\n }\n\n /**\n * Mark changeset as reverted\n */\n markReverted(): void {\n this.status = 'reverted';\n this.updateModified();\n }\n\n /**\n * Serialize to JSON\n */\n toJSON(): ChangesetData {\n return {\n name: this.name,\n description: this.description,\n created: this.created,\n modified: this.modified,\n changes: this.changes,\n status: this.status,\n };\n }\n\n /**\n * Create from JSON data\n */\n static fromJSON(data: ChangesetData): Changeset {\n return new Changeset(data);\n }\n}\n\n/**\n * Changeset Manager for storing and retrieving changesets\n */\nexport class ChangesetManager {\n private changesetsDir: string;\n\n constructor(modelPath: string) {\n this.changesetsDir = `${modelPath}/.dr/changesets`;\n }\n\n /**\n * Create a new changeset\n */\n async create(name: string, description?: string): Promise<Changeset> {\n const changeset = Changeset.create(name, description);\n await this.save(changeset);\n return changeset;\n }\n\n /**\n * Save a changeset to disk\n */\n async save(changeset: Changeset): Promise<void> {\n await ensureDir(this.changesetsDir);\n const filePath = `${this.changesetsDir}/${this.sanitizeName(changeset.name)}.json`;\n await writeJSON(filePath, changeset.toJSON(), true);\n }\n\n /**\n * Load a changeset by name\n */\n async load(name: string): Promise<Changeset | null> {\n const filePath = `${this.changesetsDir}/${this.sanitizeName(name)}.json`;\n\n if (!(await fileExists(filePath))) {\n return null;\n }\n\n const data = await readJSON<ChangesetData>(filePath);\n return Changeset.fromJSON(data);\n }\n\n /**\n * List all changesets\n */\n async list(): Promise<Changeset[]> {\n if (!(await fileExists(this.changesetsDir))) {\n return [];\n }\n\n const fs = await import('fs/promises');\n const files = await fs.readdir(this.changesetsDir);\n const changesets: Changeset[] = [];\n\n for (const file of files) {\n if (file.endsWith('.json')) {\n const data = await readJSON<ChangesetData>(\n `${this.changesetsDir}/${file}`\n );\n changesets.push(Changeset.fromJSON(data));\n }\n }\n\n return changesets;\n }\n\n /**\n * Delete a changeset\n */\n async delete(name: string): Promise<void> {\n const filePath = `${this.changesetsDir}/${this.sanitizeName(name)}.json`;\n\n if (!(await fileExists(filePath))) {\n throw new Error(`Changeset '${name}' not found`);\n }\n\n const fs = await import('fs/promises');\n await fs.unlink(filePath);\n }\n\n /**\n * Apply a changeset to the model\n */\n async apply(model: Model, name: string): Promise<ApplyResult> {\n const changeset = await this.load(name);\n\n if (!changeset) {\n throw new Error(`Changeset '${name}' not found`);\n }\n\n const result: ApplyResult = {\n changeset: name,\n applied: 0,\n failed: 0,\n errors: [],\n };\n\n for (const change of changeset.changes) {\n try {\n const layer = await model.getLayer(change.layerName);\n\n if (!layer) {\n throw new Error(`Layer '${change.layerName}' not found`);\n }\n\n if (change.type === 'add' && change.after) {\n // Add element to layer\n const elements = layer.listElements();\n const elementExists = elements.some((e) => e.id === change.elementId);\n\n if (!elementExists) {\n // Create element based on after data\n const elementData = change.after as Record<string, unknown>;\n const element = new Element({\n id: change.elementId,\n type: (elementData.type as string) || 'unknown',\n name: (elementData.name as string) || change.elementId,\n description: elementData.description as string | undefined,\n properties: elementData,\n });\n layer.addElement(element);\n result.applied++;\n }\n } else if (change.type === 'update' && change.after) {\n // Update element in layer\n const element = layer.getElement(change.elementId);\n\n if (element) {\n const elementData = change.after as Record<string, unknown>;\n Object.assign(element, elementData);\n result.applied++;\n }\n } else if (change.type === 'delete') {\n // Delete element from layer\n const element = layer.getElement(change.elementId);\n\n if (element) {\n layer.deleteElement(change.elementId);\n result.applied++;\n }\n }\n } catch (error) {\n result.failed++;\n result.errors.push({\n change,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (result.failed === 0) {\n changeset.markApplied();\n await this.save(changeset);\n }\n\n return result;\n }\n\n /**\n * Revert a changeset from the model\n */\n async revert(model: Model, name: string): Promise<RevertResult> {\n const changeset = await this.load(name);\n\n if (!changeset) {\n throw new Error(`Changeset '${name}' not found`);\n }\n\n const result: RevertResult = {\n changeset: name,\n reverted: 0,\n failed: 0,\n errors: [],\n };\n\n // Process changes in reverse order\n for (let i = changeset.changes.length - 1; i >= 0; i--) {\n const change = changeset.changes[i];\n\n try {\n const layer = await model.getLayer(change.layerName);\n\n if (!layer) {\n throw new Error(`Layer '${change.layerName}' not found`);\n }\n\n // Reverse each operation\n if (change.type === 'add') {\n // Remove the element that was added\n const element = layer.getElement(change.elementId);\n\n if (element) {\n layer.deleteElement(change.elementId);\n result.reverted++;\n }\n } else if (change.type === 'update' && change.before) {\n // Restore to previous state\n const element = layer.getElement(change.elementId);\n\n if (element) {\n const elementData = change.before as Record<string, unknown>;\n Object.assign(element, elementData);\n result.reverted++;\n }\n } else if (change.type === 'delete' && change.before) {\n // Recreate the deleted element\n const elements = layer.listElements();\n const elementExists = elements.some((e) => e.id === change.elementId);\n\n if (!elementExists) {\n const elementData = change.before as Record<string, unknown>;\n const element = new Element({\n id: change.elementId,\n type: (elementData.type as string) || 'unknown',\n name: (elementData.name as string) || change.elementId,\n description: elementData.description as string | undefined,\n properties: elementData,\n });\n layer.addElement(element);\n result.reverted++;\n }\n }\n } catch (error) {\n result.failed++;\n result.errors.push({\n change,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (result.failed === 0) {\n changeset.markReverted();\n await this.save(changeset);\n }\n\n return result;\n }\n\n /**\n * Sanitize changeset name for use as filename\n */\n private sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '');\n }\n}\n\n/**\n * Result of applying a changeset\n */\nexport interface ApplyResult {\n changeset: string;\n applied: number;\n failed: number;\n errors: Array<{\n change: Change;\n error: string;\n }>;\n}\n\n/**\n * Result of reverting a changeset\n */\nexport interface RevertResult {\n changeset: string;\n reverted: number;\n failed: number;\n errors: Array<{\n change: Change;\n error: string;\n }>;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Changeset - Represents a collection of model changes.\n *\n * Changesets group related modifications to the architecture model for:\n * - Staging changes before committing to the base model\n * - Audit trail of model changes with before/after snapshots\n * - Collaboration and change tracking across team members\n *\n * Uses the staging workflow (staged/committed/discarded).\n */\n\n/**\n * Represents a single change in a changeset.\n * Records element mutations with before/after snapshots for audit purposes.\n */\nexport interface Change {\n type: \"add\" | \"update\" | \"delete\" | \"relationship-add\" | \"relationship-delete\";\n elementId: string; // For relationships: composite key \"source::predicate::target\"\n layerName: string; // For relationships: source element's layer\n before?: Record<string, unknown>; // Element/relationship state before change\n after?: Record<string, unknown>; // Element/relationship state after change\n timestamp?: string; // ISO timestamp; optional in interface but always set before storage\n}\n\n/**\n * Represents a staged change with sequence number for ordered replay.\n * Used in the staging workflow to ensure changes are applied in order during commit.\n */\nexport interface StagedChange extends Change {\n readonly sequenceNumber: number; // 0-based index for ordering during commit replay\n}\n\n/**\n * Status values for changesets in the staging workflow.\n *\n * - 'staged': Created and active for staging changes (can accept new changes)\n * - 'committed': Changes have been committed to base model\n * - 'discarded': Changes were discarded without committing\n */\nexport type ChangesetStatus = \"staged\" | \"committed\" | \"discarded\";\n\n/**\n * Changeset data with staging semantics and metadata.\n * Includes id and base snapshot for drift detection and auto-computed stats.\n */\nexport interface StagedChangesetData {\n id: string; // Unique changeset ID\n name: string;\n description?: string;\n created: string; // ISO timestamp of creation\n modified: string; // ISO timestamp of last modification\n status: ChangesetStatus;\n baseSnapshot: string; // SHA256 hash of base model at creation (for drift detection)\n changes: Change[] | StagedChange[]; // Changes (with optional sequence numbers)\n stats?: {\n additions: number;\n modifications: number;\n deletions: number;\n };\n}\n\n/**\n * Changeset class for managing model changes.\n * Represents a staging workflow changeset (staged/committed/discarded).\n *\n * Stats are computed on-demand from the changes array, ensuring consistency.\n */\nexport class Changeset {\n name: string;\n description?: string;\n created: string;\n modified: string;\n changes: Change[] = [];\n status: ChangesetStatus = \"staged\";\n\n // Staging workflow fields (required)\n id: string;\n baseSnapshot: string;\n\n /**\n * Get statistics derived from changes array.\n * Computed on-demand to ensure always accurate regardless of how changes were added.\n *\n * @returns Statistics object with count of additions, modifications, deletions\n */\n get stats(): {\n additions: number;\n modifications: number;\n deletions: number;\n } {\n // Compute stats from changes array on-demand (never stale)\n const additions = this.changes.filter((c) => c.type === \"add\" || c.type === \"relationship-add\").length;\n const modifications = this.changes.filter((c) => c.type === \"update\").length;\n const deletions = this.changes.filter((c) => c.type === \"delete\" || c.type === \"relationship-delete\").length;\n\n return { additions, modifications, deletions };\n }\n\n /**\n * Create changeset from data object.\n * Accepts only StagedChangesetData format with id and baseSnapshot.\n *\n * @param data - Changeset data from storage or API\n */\n constructor(data: StagedChangesetData) {\n this.name = data.name;\n this.description = data.description;\n this.created = data.created;\n this.modified = data.modified;\n // Store changes; preserve sequenceNumber if present from storage\n this.changes = (data.changes || []).map((change) => {\n const { type, elementId, layerName, before, after, timestamp, sequenceNumber } = change as any;\n const result: any = { type, elementId, layerName, before, after, timestamp };\n // Preserve sequenceNumber if it exists (from loaded StagedChange)\n if (typeof sequenceNumber === \"number\") {\n result.sequenceNumber = sequenceNumber;\n }\n return result as Change;\n });\n this.status = data.status || \"staged\";\n this.id = data.id;\n this.baseSnapshot = data.baseSnapshot;\n // Note: Stats are computed from changes array via getter; ignore any stored stats\n }\n\n /**\n * Create a new changeset with staged status.\n *\n * @param name - Human-readable name for the changeset\n * @param description - Optional description of changes\n * @param id - Unique changeset ID (required)\n * @param baseSnapshot - SHA256 hash of base model at creation (required)\n * @returns New Changeset instance in staged status\n */\n static create(\n name: string,\n description: string | undefined,\n id: string,\n baseSnapshot: string\n ): Changeset {\n const now = new Date().toISOString();\n return new Changeset({\n name,\n description,\n created: now,\n modified: now,\n changes: [],\n status: \"staged\",\n id,\n baseSnapshot,\n });\n }\n\n /**\n * Add a change to the changeset.\n * Records element mutation with before/after snapshots for audit purposes.\n *\n * @param type - Type of change (add, update, delete)\n * @param elementId - ID of the element being changed\n * @param layerName - Layer containing the element\n * @param before - Element state before change (for update/delete operations)\n * @param after - Element state after change (for add/update operations)\n * @throws No exceptions; updates modified timestamp on success\n */\n addChange(\n type: \"add\" | \"update\" | \"delete\",\n elementId: string,\n layerName: string,\n before?: Record<string, unknown>,\n after?: Record<string, unknown>\n ): void {\n this.changes.push({\n type,\n elementId,\n layerName,\n before,\n after,\n timestamp: new Date().toISOString(),\n });\n this.updateModified();\n }\n\n /**\n * Update the modified timestamp to current time.\n */\n updateModified(): void {\n this.modified = new Date().toISOString();\n }\n\n /**\n * Get the total number of changes in this changeset.\n *\n * @returns Number of changes (add + update + delete)\n */\n getChangeCount(): number {\n return this.changes.length;\n }\n\n /**\n * Get all changes of a specific type.\n *\n * @param type - Type of changes to filter for\n * @returns Array of changes matching the type\n */\n getChangesByType(type: \"add\" | \"update\" | \"delete\"): Change[] {\n return this.changes.filter((c) => c.type === type);\n }\n\n /**\n * Mark changeset as staged.\n * Enables the changeset to accept new changes via staging operations.\n * Updates status and modified timestamp.\n */\n markStaged(): void {\n this.status = \"staged\";\n this.updateModified();\n }\n\n /**\n * Mark changeset as committed.\n * Indicates changes have been committed to the base model.\n * Updates status and modified timestamp.\n */\n markCommitted(): void {\n this.status = \"committed\";\n this.updateModified();\n }\n\n /**\n * Mark changeset as discarded.\n * Indicates changes have been discarded without committing.\n * Updates status and modified timestamp.\n */\n markDiscarded(): void {\n this.status = \"discarded\";\n this.updateModified();\n }\n\n /**\n * Serialize changeset to JSON.\n * Always returns StagedChangesetData format with sequenceNumbers added.\n *\n * @returns Serialized changeset data suitable for storage\n */\n toJSON(): StagedChangesetData {\n return {\n id: this.id,\n name: this.name,\n description: this.description,\n created: this.created,\n modified: this.modified,\n baseSnapshot: this.baseSnapshot,\n status: this.status,\n changes: this.changes.map((change, idx) => ({\n ...change,\n sequenceNumber: idx,\n })),\n stats: this.stats,\n };\n }\n\n /**\n * Deserialize changeset from JSON data.\n * Accepts StagedChangesetData format.\n *\n * @param data - Serialized changeset data\n * @returns New Changeset instance\n */\n static fromJSON(data: StagedChangesetData): Changeset {\n return new Changeset(data);\n }\n}\n"],
5
+ "mappings": "AAmEM,MAAO,UAAS;EACpB;EACA;EACA;EACA;EACA,UAAoB,CAAA;EACpB,SAA0B;;EAG1B;EACA;;;;;;;EAQA,IAAI,QAAK;AAMP,UAAM,YAAY,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,SAAS,kBAAkB,EAAE,QAC1F,gBAAgB,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,QAChE,YAAY,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,qBAAqB,EAAE;AAEtG,WAAO,EAAE,WAAW,eAAe,UAAS;EAC9C;;;;;;;EAQA,YAAY,MAAyB;AACnC,SAAK,OAAO,KAAK,MACjB,KAAK,cAAc,KAAK,aACxB,KAAK,UAAU,KAAK,SACpB,KAAK,WAAW,KAAK,UAErB,KAAK,WAAW,KAAK,WAAW,CAAA,GAAI,IAAI,CAAC,WAAU;AACjD,YAAM,EAAE,MAAM,WAAW,WAAW,QAAQ,OAAO,WAAW,eAAc,IAAK,QAC3E,SAAc,EAAE,MAAM,WAAW,WAAW,QAAQ,OAAO,UAAS;AAE1E,aAAI,OAAO,kBAAmB,aAC5B,OAAO,iBAAiB,iBAEnB;IACT,CAAC,GACD,KAAK,SAAS,KAAK,UAAU,UAC7B,KAAK,KAAK,KAAK,IACf,KAAK,eAAe,KAAK;EAE3B;;;;;;;;;;EAWA,OAAO,OACL,MACA,aACA,IACA,cAAoB;AAEpB,UAAM,OAAM,oBAAI,KAAI,GAAG,YAAW;AAClC,WAAO,IAAI,UAAU;MACnB;MACA;MACA,SAAS;MACT,UAAU;MACV,SAAS,CAAA;MACT,QAAQ;MACR;MACA;KACD;EACH;;;;;;;;;;;;EAaA,UACE,MACA,WACA,WACA,QACA,OAA+B;AAE/B,SAAK,QAAQ,KAAK;MAChB;MACA;MACA;MACA;MACA;MACA,YAAW,oBAAI,KAAI,GAAG,YAAW;KAClC,GACD,KAAK,eAAc;EACrB;;;;EAKA,iBAAc;AACZ,SAAK,YAAW,oBAAI,KAAI,GAAG,YAAW;EACxC;;;;;;EAOA,iBAAc;AACZ,WAAO,KAAK,QAAQ;EACtB;;;;;;;EAQA,iBAAiB,MAAiC;AAChD,WAAO,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;EACnD;;;;;;EAOA,aAAU;AACR,SAAK,SAAS,UACd,KAAK,eAAc;EACrB;;;;;;EAOA,gBAAa;AACX,SAAK,SAAS,aACd,KAAK,eAAc;EACrB;;;;;;EAOA,gBAAa;AACX,SAAK,SAAS,aACd,KAAK,eAAc;EACrB;;;;;;;EAQA,SAAM;AACJ,WAAO;MACL,IAAI,KAAK;MACT,MAAM,KAAK;MACX,aAAa,KAAK;MAClB,SAAS,KAAK;MACd,UAAU,KAAK;MACf,cAAc,KAAK;MACnB,QAAQ,KAAK;MACb,SAAS,KAAK,QAAQ,IAAI,CAAC,QAAQ,SAAS;QAC1C,GAAG;QACH,gBAAgB;QAChB;MACF,OAAO,KAAK;;EAEhB;;;;;;;;EASA,OAAO,SAAS,MAAyB;AACvC,WAAO,IAAI,UAAU,IAAI;EAC3B;;",
6
6
  "names": []
7
7
  }
@@ -310,8 +310,10 @@ class DependencyTracker {
310
310
  return [];
311
311
  const graph = this.getGraph(), orphaned = [];
312
312
  for (const layer of this.model.layers.values())
313
- for (const element of layer.elements.values())
314
- graph.hasNode(element.id) ? graph.degree(element.id) === 0 && orphaned.push(element) : orphaned.push(element);
313
+ for (const element of layer.elements.values()) {
314
+ const nodeKey = element.path || element.id;
315
+ graph.hasNode(nodeKey) ? graph.degree(nodeKey) === 0 && orphaned.push(element) : orphaned.push(element);
316
+ }
315
317
  return orphaned;
316
318
  }
317
319
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/core/dependency-tracker.ts"],
4
- "sourcesContent": ["import Graph from 'graphology';\nimport { ReferenceRegistry } from './reference-registry.js';\nimport { Model } from './model.js';\n\n/**\n * Direction to trace dependencies (matches Python CLI TraceDirection enum)\n */\nexport enum TraceDirection {\n UP = 'up', // Find what this depends on (successors/descendants)\n DOWN = 'down', // Find what depends on this (predecessors/ancestors)\n BOTH = 'both' // Both directions\n}\n\n/**\n * Represents a dependency path between two elements\n */\nexport interface DependencyPath {\n source: string;\n target: string;\n path: string[];\n depth: number;\n relationship_types: string[];\n}\n\n/**\n * Dependency tracker - analyzes dependencies between elements\n *\n * Uses reference registry and graph algorithms to provide\n * dependency analysis and impact assessment.\n *\n * Matches Python CLI behavior from dependency_tracker.py\n */\nexport class DependencyTracker {\n private registry?: ReferenceRegistry;\n private graph: Graph;\n private model?: Model;\n\n constructor(registryOrGraph: ReferenceRegistry | Graph, model?: Model) {\n if (registryOrGraph instanceof Graph) {\n this.graph = registryOrGraph;\n } else {\n this.registry = registryOrGraph;\n this.graph = registryOrGraph.getDependencyGraph();\n }\n this.model = model;\n }\n\n /**\n * Get dependency graph\n */\n private getGraph(): Graph {\n if (this.registry) {\n // Rebuild from registry each time to reflect new references\n this.graph = this.registry.getDependencyGraph();\n }\n return this.graph;\n }\n\n /**\n * Trace dependencies from an element\n *\n * @param elementId - Element ID to start from\n * @param direction - Direction to trace (up, down, both)\n * @param maxDepth - Maximum depth to trace (null = unlimited)\n * @returns Array of dependent element IDs\n */\n traceDependencies(\n elementId: string,\n direction: TraceDirection = TraceDirection.BOTH,\n maxDepth: number | null = null\n ): string[] {\n const graph = this.getGraph();\n\n if (!graph.hasNode(elementId)) {\n return [];\n }\n\n const dependencies = new Set<string>();\n\n // Trace upward (what this element depends on - successors)\n if (direction === TraceDirection.UP || direction === TraceDirection.BOTH) {\n const upDeps = this._traceUp(graph, elementId, maxDepth);\n upDeps.forEach(id => dependencies.add(id));\n }\n\n // Trace downward (what depends on this element - predecessors)\n if (direction === TraceDirection.DOWN || direction === TraceDirection.BOTH) {\n const downDeps = this._traceDown(graph, elementId, maxDepth);\n downDeps.forEach(id => dependencies.add(id));\n }\n\n return Array.from(dependencies);\n }\n\n /**\n * Trace upward dependencies (what element depends on - successors)\n * Private helper matching Python CLI behavior\n */\n private _traceUp(graph: Graph, elementId: string, maxDepth: number | null): Set<string> {\n if (maxDepth === null) {\n // Get all descendants (unlimited depth)\n return this._getDescendants(graph, elementId);\n } else {\n // Get descendants within depth using BFS\n return this._getDescendantsLimited(graph, elementId, maxDepth);\n }\n }\n\n /**\n * Trace downward dependencies (what depends on element - predecessors)\n * Private helper matching Python CLI behavior\n */\n private _traceDown(graph: Graph, elementId: string, maxDepth: number | null): Set<string> {\n if (maxDepth === null) {\n // Get all ancestors (unlimited depth)\n return this._getAncestors(graph, elementId);\n } else {\n // Get ancestors within depth using BFS\n return this._getAncestorsLimited(graph, elementId, maxDepth);\n }\n }\n\n /**\n * Get all descendants (reachable via outgoing edges) - DFS\n * Equivalent to networkx.descendants()\n */\n private _getDescendants(graph: Graph, startNode: string): Set<string> {\n const visited = new Set<string>();\n const stack = [startNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.outNeighbors(node)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n stack.push(neighbor);\n }\n }\n }\n\n return visited;\n }\n\n /**\n * Get ancestors (reachable via incoming edges) - DFS\n * Equivalent to networkx.ancestors()\n */\n private _getAncestors(graph: Graph, startNode: string): Set<string> {\n const visited = new Set<string>();\n const stack = [startNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.inNeighbors(node)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n stack.push(neighbor);\n }\n }\n }\n\n return visited;\n }\n\n /**\n * Get descendants within max_depth using BFS level-by-level\n * Matches Python CLI behavior exactly\n */\n private _getDescendantsLimited(graph: Graph, startNode: string, maxDepth: number): Set<string> {\n const descendants = new Set<string>();\n let currentLevel = new Set([startNode]);\n\n for (let depth = 0; depth < maxDepth; depth++) {\n const nextLevel = new Set<string>();\n\n for (const node of currentLevel) {\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.outNeighbors(node)) {\n nextLevel.add(neighbor);\n }\n }\n\n nextLevel.forEach(id => descendants.add(id));\n currentLevel = nextLevel;\n\n if (currentLevel.size === 0) {\n break;\n }\n }\n\n return descendants;\n }\n\n /**\n * Get ancestors within max_depth using BFS level-by-level\n * Matches Python CLI behavior exactly\n */\n private _getAncestorsLimited(graph: Graph, startNode: string, maxDepth: number): Set<string> {\n const ancestors = new Set<string>();\n let currentLevel = new Set([startNode]);\n\n for (let depth = 0; depth < maxDepth; depth++) {\n const nextLevel = new Set<string>();\n\n for (const node of currentLevel) {\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.inNeighbors(node)) {\n nextLevel.add(neighbor);\n }\n }\n\n nextLevel.forEach(id => ancestors.add(id));\n currentLevel = nextLevel;\n\n if (currentLevel.size === 0) {\n break;\n }\n }\n\n return ancestors;\n }\n\n /**\n * Find all dependency paths between two elements\n *\n * @param sourceId - Source element ID\n * @param targetId - Target element ID\n * @param maxPaths - Maximum number of paths to return\n * @returns Array of dependency paths\n */\n findDependencyPaths(\n sourceId: string,\n targetId: string,\n maxPaths: number = 10\n ): DependencyPath[] {\n const graph = this.getGraph();\n\n if (!graph.hasNode(sourceId) || !graph.hasNode(targetId)) {\n return [];\n }\n\n // Find all simple paths (no cycles)\n const paths = this._findAllSimplePaths(graph, sourceId, targetId, maxPaths);\n\n // Convert to DependencyPath objects\n return paths.map(path => {\n // Get relationship types along path\n const relationshipTypes: string[] = [];\n for (let i = 0; i < path.length - 1; i++) {\n const edgeAttrs = graph.getEdgeAttributes(path[i], path[i + 1]);\n relationshipTypes.push(edgeAttrs?.type || 'unknown');\n }\n\n return {\n source: sourceId,\n target: targetId,\n path,\n depth: path.length - 1,\n relationship_types: relationshipTypes\n };\n });\n }\n\n /**\n * Find all simple paths between source and target\n * Implements DFS path-finding similar to networkx.all_simple_paths\n */\n private _findAllSimplePaths(\n graph: Graph,\n source: string,\n target: string,\n maxPaths: number\n ): string[][] {\n const paths: string[][] = [];\n const visited = new Set<string>();\n\n const dfs = (current: string, path: string[]) => {\n if (paths.length >= maxPaths) {\n return;\n }\n\n if (current === target) {\n paths.push([...path, current]);\n return;\n }\n\n visited.add(current);\n path.push(current);\n\n if (graph.hasNode(current)) {\n for (const neighbor of graph.outNeighbors(current)) {\n if (!visited.has(neighbor)) {\n dfs(neighbor, path);\n }\n }\n }\n\n path.pop();\n visited.delete(current);\n };\n\n dfs(source, []);\n return paths;\n }\n\n /**\n * Find hub elements (elements with many connections)\n *\n * @param threshold - Minimum number of connections to be considered a hub\n * @returns Array of [elementId, connectionCount] tuples, sorted by count descending\n */\n getHubElements(threshold: number = 10): [string, number][] {\n const graph = this.getGraph();\n const hubs: [string, number][] = [];\n\n for (const node of graph.nodes()) {\n const degree = graph.degree(node);\n if (degree >= threshold) {\n hubs.push([node, degree]);\n }\n }\n\n // Sort by degree descending\n hubs.sort((a, b) => b[1] - a[1]);\n\n return hubs;\n }\n\n /**\n * Get direct dependents (incoming edges)\n */\n getDependents(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return graph.inNeighbors(elementId);\n }\n\n /**\n * Get direct dependencies (outgoing edges)\n */\n getDependencies(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return graph.outNeighbors(elementId);\n }\n\n /**\n * Get all elements that transitively depend on the given element (ancestors)\n */\n getTransitiveDependents(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return Array.from(this._getAncestors(graph, elementId));\n }\n\n /**\n * Get all elements this element transitively depends on (descendants)\n */\n getTransitiveDependencies(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return Array.from(this._getDescendants(graph, elementId));\n }\n\n /**\n * Detect cycles in the dependency graph\n */\n detectCycles(): string[][] {\n const graph = this.getGraph();\n const visited = new Set<string>();\n const stack = new Set<string>();\n const path: string[] = [];\n const cycleMap = new Map<string, string[]>();\n\n const canonicalKey = (cycle: string[]): string => {\n // Normalize cycle representation to avoid duplicates\n const unique = Array.from(new Set(cycle));\n unique.sort();\n return unique.join('|');\n };\n\n const dfs = (node: string) => {\n visited.add(node);\n stack.add(node);\n path.push(node);\n\n for (const neighbor of graph.outNeighbors(node)) {\n if (!visited.has(neighbor)) {\n dfs(neighbor);\n } else if (stack.has(neighbor)) {\n // Found a cycle, capture the slice from neighbor to current\n const idx = path.indexOf(neighbor);\n if (idx !== -1) {\n const cycle = path.slice(idx);\n const key = canonicalKey(cycle);\n if (!cycleMap.has(key)) {\n cycleMap.set(key, [...cycle]);\n }\n }\n }\n }\n\n stack.delete(node);\n path.pop();\n };\n\n for (const node of graph.nodes()) {\n if (!visited.has(node)) {\n dfs(node);\n }\n }\n\n return Array.from(cycleMap.values());\n }\n\n /**\n * Calculate basic graph metrics\n */\n getMetrics(): { nodeCount: number; edgeCount: number; cycleCount: number; connectedComponents: number } {\n const graph = this.getGraph();\n\n const nodeCount = graph.order;\n const edgeCount = graph.size;\n const cycleCount = this.detectCycles().length;\n\n // Count weakly connected components\n const visited = new Set<string>();\n let connectedComponents = 0;\n\n const bfs = (start: string) => {\n const queue = [start];\n visited.add(start);\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n const neighbors = new Set<string>([\n ...graph.outNeighbors(node),\n ...graph.inNeighbors(node)\n ]);\n\n for (const neighbor of neighbors) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n queue.push(neighbor);\n }\n }\n }\n };\n\n for (const node of graph.nodes()) {\n if (!visited.has(node)) {\n connectedComponents += 1;\n bfs(node);\n }\n }\n\n return { nodeCount, edgeCount, cycleCount, connectedComponents };\n }\n\n /**\n * Find elements with no incoming edges\n */\n findSourceElements(): string[] {\n const graph = this.getGraph();\n const sources: string[] = [];\n\n for (const node of graph.nodes()) {\n if (graph.inNeighbors(node).length === 0) {\n sources.push(node);\n }\n }\n\n return sources;\n }\n\n /**\n * Find elements with no outgoing edges\n */\n findSinkElements(): string[] {\n const graph = this.getGraph();\n const sinks: string[] = [];\n\n for (const node of graph.nodes()) {\n if (graph.outNeighbors(node).length === 0) {\n sinks.push(node);\n }\n }\n\n return sinks;\n }\n\n /**\n * Calculate how many elements would be impacted if this element changed\n * (all ancestors/predecessors excluding the element itself)\n */\n getImpactRadius(elementId: string): number {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return 0;\n const impacted = this._getAncestors(graph, elementId);\n return impacted.size;\n }\n\n /**\n * Get longest dependency chain depth from this element (outgoing edges)\n */\n getDependencyDepth(elementId: string): number {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return -1;\n\n const memo = new Map<string, number>();\n const stack = new Set<string>();\n\n const dfsDepth = (node: string): number => {\n if (memo.has(node)) return memo.get(node)!;\n if (stack.has(node)) return 0; // break cycles\n\n stack.add(node);\n let maxDepth = 0;\n\n for (const neighbor of graph.outNeighbors(node)) {\n const neighborDepth = dfsDepth(neighbor);\n maxDepth = Math.max(maxDepth, 1 + neighborDepth);\n }\n\n stack.delete(node);\n memo.set(node, maxDepth);\n return maxDepth;\n };\n\n return dfsDepth(elementId);\n }\n\n /**\n * Group dependencies by layer (requires model)\n */\n getDependencyLayers(elementId: string): Record<string, string[]> {\n if (!this.model) return {};\n\n const byLayer: Record<string, string[]> = {};\n const dependencies = this.traceDependencies(elementId, TraceDirection.BOTH);\n\n for (const depId of dependencies) {\n const element = this.model.getElementById(depId);\n if (!element || !element.layer) continue;\n\n if (!byLayer[element.layer]) {\n byLayer[element.layer] = [];\n }\n byLayer[element.layer].push(depId);\n }\n\n return byLayer;\n }\n\n /**\n * Find elements with no references (requires model)\n */\n getOrphanedElements(): any[] {\n if (!this.model) return [];\n\n const graph = this.getGraph();\n const orphaned: any[] = [];\n\n for (const layer of this.model.layers.values()) {\n for (const element of layer.elements.values()) {\n if (!graph.hasNode(element.id)) {\n orphaned.push(element);\n } else if (graph.degree(element.id) === 0) {\n orphaned.push(element);\n }\n }\n }\n\n return orphaned;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import Graph from \"graphology\";\nimport { ReferenceRegistry } from \"./reference-registry.js\";\nimport { Model } from \"./model.js\";\nimport type { Element } from \"./element.js\";\n\n/**\n * Direction to trace dependencies (matches Python CLI TraceDirection enum)\n */\nexport enum TraceDirection {\n UP = \"up\", // Find what this depends on (successors/descendants)\n DOWN = \"down\", // Find what depends on this (predecessors/ancestors)\n BOTH = \"both\", // Both directions\n}\n\n/**\n * Represents a dependency path between two elements\n */\nexport interface DependencyPath {\n source: string;\n target: string;\n path: string[];\n depth: number;\n relationship_types: string[];\n}\n\n/**\n * Dependency tracker - analyzes dependencies between elements\n *\n * Uses reference registry and graph algorithms to provide\n * dependency analysis and impact assessment.\n *\n * Matches Python CLI behavior from dependency_tracker.py\n */\nexport class DependencyTracker {\n private registry?: ReferenceRegistry;\n private graph: Graph;\n private model?: Model;\n\n constructor(registryOrGraph: ReferenceRegistry | Graph, model?: Model) {\n if (registryOrGraph instanceof Graph) {\n this.graph = registryOrGraph;\n } else {\n this.registry = registryOrGraph;\n this.graph = registryOrGraph.getDependencyGraph();\n }\n this.model = model;\n }\n\n /**\n * Get dependency graph\n */\n private getGraph(): Graph {\n if (this.registry) {\n // Rebuild from registry each time to reflect new references\n this.graph = this.registry.getDependencyGraph();\n }\n return this.graph;\n }\n\n /**\n * Trace dependencies from an element\n *\n * @param elementId - Element ID to start from\n * @param direction - Direction to trace (up, down, both)\n * @param maxDepth - Maximum depth to trace (null = unlimited)\n * @returns Array of dependent element IDs\n */\n traceDependencies(\n elementId: string,\n direction: TraceDirection = TraceDirection.BOTH,\n maxDepth: number | null = null\n ): string[] {\n const graph = this.getGraph();\n\n if (!graph.hasNode(elementId)) {\n return [];\n }\n\n const dependencies = new Set<string>();\n\n // Trace upward (what this element depends on - successors)\n if (direction === TraceDirection.UP || direction === TraceDirection.BOTH) {\n const upDeps = this._traceUp(graph, elementId, maxDepth);\n upDeps.forEach((id) => dependencies.add(id));\n }\n\n // Trace downward (what depends on this element - predecessors)\n if (direction === TraceDirection.DOWN || direction === TraceDirection.BOTH) {\n const downDeps = this._traceDown(graph, elementId, maxDepth);\n downDeps.forEach((id) => dependencies.add(id));\n }\n\n return Array.from(dependencies);\n }\n\n /**\n * Trace upward dependencies (what element depends on - successors)\n * Private helper matching Python CLI behavior\n */\n private _traceUp(graph: Graph, elementId: string, maxDepth: number | null): Set<string> {\n if (maxDepth === null) {\n // Get all descendants (unlimited depth)\n return this._getDescendants(graph, elementId);\n } else {\n // Get descendants within depth using BFS\n return this._getDescendantsLimited(graph, elementId, maxDepth);\n }\n }\n\n /**\n * Trace downward dependencies (what depends on element - predecessors)\n * Private helper matching Python CLI behavior\n */\n private _traceDown(graph: Graph, elementId: string, maxDepth: number | null): Set<string> {\n if (maxDepth === null) {\n // Get all ancestors (unlimited depth)\n return this._getAncestors(graph, elementId);\n } else {\n // Get ancestors within depth using BFS\n return this._getAncestorsLimited(graph, elementId, maxDepth);\n }\n }\n\n /**\n * Get all descendants (reachable via outgoing edges) - DFS\n * Equivalent to networkx.descendants()\n */\n private _getDescendants(graph: Graph, startNode: string): Set<string> {\n const visited = new Set<string>();\n const stack = [startNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.outNeighbors(node)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n stack.push(neighbor);\n }\n }\n }\n\n return visited;\n }\n\n /**\n * Get ancestors (reachable via incoming edges) - DFS\n * Equivalent to networkx.ancestors()\n */\n private _getAncestors(graph: Graph, startNode: string): Set<string> {\n const visited = new Set<string>();\n const stack = [startNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.inNeighbors(node)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n stack.push(neighbor);\n }\n }\n }\n\n return visited;\n }\n\n /**\n * Get descendants within max_depth using BFS level-by-level\n * Matches Python CLI behavior exactly\n */\n private _getDescendantsLimited(graph: Graph, startNode: string, maxDepth: number): Set<string> {\n const descendants = new Set<string>();\n let currentLevel = new Set([startNode]);\n\n for (let depth = 0; depth < maxDepth; depth++) {\n const nextLevel = new Set<string>();\n\n for (const node of currentLevel) {\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.outNeighbors(node)) {\n nextLevel.add(neighbor);\n }\n }\n\n nextLevel.forEach((id) => descendants.add(id));\n currentLevel = nextLevel;\n\n if (currentLevel.size === 0) {\n break;\n }\n }\n\n return descendants;\n }\n\n /**\n * Get ancestors within max_depth using BFS level-by-level\n * Matches Python CLI behavior exactly\n */\n private _getAncestorsLimited(graph: Graph, startNode: string, maxDepth: number): Set<string> {\n const ancestors = new Set<string>();\n let currentLevel = new Set([startNode]);\n\n for (let depth = 0; depth < maxDepth; depth++) {\n const nextLevel = new Set<string>();\n\n for (const node of currentLevel) {\n if (!graph.hasNode(node)) continue;\n\n for (const neighbor of graph.inNeighbors(node)) {\n nextLevel.add(neighbor);\n }\n }\n\n nextLevel.forEach((id) => ancestors.add(id));\n currentLevel = nextLevel;\n\n if (currentLevel.size === 0) {\n break;\n }\n }\n\n return ancestors;\n }\n\n /**\n * Find all dependency paths between two elements\n *\n * @param sourceId - Source element ID\n * @param targetId - Target element ID\n * @param maxPaths - Maximum number of paths to return\n * @returns Array of dependency paths\n */\n findDependencyPaths(sourceId: string, targetId: string, maxPaths: number = 10): DependencyPath[] {\n const graph = this.getGraph();\n\n if (!graph.hasNode(sourceId) || !graph.hasNode(targetId)) {\n return [];\n }\n\n // Find all simple paths (no cycles)\n const paths = this._findAllSimplePaths(graph, sourceId, targetId, maxPaths);\n\n // Convert to DependencyPath objects\n return paths.map((path) => {\n // Get relationship types along path\n const relationshipTypes: string[] = [];\n for (let i = 0; i < path.length - 1; i++) {\n const edgeAttrs = graph.getEdgeAttributes(path[i], path[i + 1]);\n relationshipTypes.push(edgeAttrs?.type || \"unknown\");\n }\n\n return {\n source: sourceId,\n target: targetId,\n path,\n depth: path.length - 1,\n relationship_types: relationshipTypes,\n };\n });\n }\n\n /**\n * Find all simple paths between source and target\n * Implements DFS path-finding similar to networkx.all_simple_paths\n */\n private _findAllSimplePaths(\n graph: Graph,\n source: string,\n target: string,\n maxPaths: number\n ): string[][] {\n const paths: string[][] = [];\n const visited = new Set<string>();\n\n const dfs = (current: string, path: string[]) => {\n if (paths.length >= maxPaths) {\n return;\n }\n\n if (current === target) {\n paths.push([...path, current]);\n return;\n }\n\n visited.add(current);\n path.push(current);\n\n if (graph.hasNode(current)) {\n for (const neighbor of graph.outNeighbors(current)) {\n if (!visited.has(neighbor)) {\n dfs(neighbor, path);\n }\n }\n }\n\n path.pop();\n visited.delete(current);\n };\n\n dfs(source, []);\n return paths;\n }\n\n /**\n * Find hub elements (elements with many connections)\n *\n * @param threshold - Minimum number of connections to be considered a hub\n * @returns Array of [elementId, connectionCount] tuples, sorted by count descending\n */\n getHubElements(threshold: number = 10): [string, number][] {\n const graph = this.getGraph();\n const hubs: [string, number][] = [];\n\n for (const node of graph.nodes()) {\n const degree = graph.degree(node);\n if (degree >= threshold) {\n hubs.push([node, degree]);\n }\n }\n\n // Sort by degree descending\n hubs.sort((a, b) => b[1] - a[1]);\n\n return hubs;\n }\n\n /**\n * Get direct dependents (incoming edges)\n */\n getDependents(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return graph.inNeighbors(elementId);\n }\n\n /**\n * Get direct dependencies (outgoing edges)\n */\n getDependencies(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return graph.outNeighbors(elementId);\n }\n\n /**\n * Get all elements that transitively depend on the given element (ancestors)\n */\n getTransitiveDependents(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return Array.from(this._getAncestors(graph, elementId));\n }\n\n /**\n * Get all elements this element transitively depends on (descendants)\n */\n getTransitiveDependencies(elementId: string): string[] {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return [];\n return Array.from(this._getDescendants(graph, elementId));\n }\n\n /**\n * Detect cycles in the dependency graph\n */\n detectCycles(): string[][] {\n const graph = this.getGraph();\n const visited = new Set<string>();\n const stack = new Set<string>();\n const path: string[] = [];\n const cycleMap = new Map<string, string[]>();\n\n const canonicalKey = (cycle: string[]): string => {\n // Normalize cycle representation to avoid duplicates\n const unique = Array.from(new Set(cycle));\n unique.sort();\n return unique.join(\"|\");\n };\n\n const dfs = (node: string) => {\n visited.add(node);\n stack.add(node);\n path.push(node);\n\n for (const neighbor of graph.outNeighbors(node)) {\n if (!visited.has(neighbor)) {\n dfs(neighbor);\n } else if (stack.has(neighbor)) {\n // Found a cycle, capture the slice from neighbor to current\n const idx = path.indexOf(neighbor);\n if (idx !== -1) {\n const cycle = path.slice(idx);\n const key = canonicalKey(cycle);\n if (!cycleMap.has(key)) {\n cycleMap.set(key, [...cycle]);\n }\n }\n }\n }\n\n stack.delete(node);\n path.pop();\n };\n\n for (const node of graph.nodes()) {\n if (!visited.has(node)) {\n dfs(node);\n }\n }\n\n return Array.from(cycleMap.values());\n }\n\n /**\n * Calculate basic graph metrics\n */\n getMetrics(): {\n nodeCount: number;\n edgeCount: number;\n cycleCount: number;\n connectedComponents: number;\n } {\n const graph = this.getGraph();\n\n const nodeCount = graph.order;\n const edgeCount = graph.size;\n const cycleCount = this.detectCycles().length;\n\n // Count weakly connected components\n const visited = new Set<string>();\n let connectedComponents = 0;\n\n const bfs = (start: string) => {\n const queue = [start];\n visited.add(start);\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n const neighbors = new Set<string>([\n ...graph.outNeighbors(node),\n ...graph.inNeighbors(node),\n ]);\n\n for (const neighbor of neighbors) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n queue.push(neighbor);\n }\n }\n }\n };\n\n for (const node of graph.nodes()) {\n if (!visited.has(node)) {\n connectedComponents += 1;\n bfs(node);\n }\n }\n\n return { nodeCount, edgeCount, cycleCount, connectedComponents };\n }\n\n /**\n * Find elements with no incoming edges\n */\n findSourceElements(): string[] {\n const graph = this.getGraph();\n const sources: string[] = [];\n\n for (const node of graph.nodes()) {\n if (graph.inNeighbors(node).length === 0) {\n sources.push(node);\n }\n }\n\n return sources;\n }\n\n /**\n * Find elements with no outgoing edges\n */\n findSinkElements(): string[] {\n const graph = this.getGraph();\n const sinks: string[] = [];\n\n for (const node of graph.nodes()) {\n if (graph.outNeighbors(node).length === 0) {\n sinks.push(node);\n }\n }\n\n return sinks;\n }\n\n /**\n * Calculate how many elements would be impacted if this element changed\n * (all ancestors/predecessors excluding the element itself)\n */\n getImpactRadius(elementId: string): number {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return 0;\n const impacted = this._getAncestors(graph, elementId);\n return impacted.size;\n }\n\n /**\n * Get longest dependency chain depth from this element (outgoing edges)\n */\n getDependencyDepth(elementId: string): number {\n const graph = this.getGraph();\n if (!graph.hasNode(elementId)) return -1;\n\n const memo = new Map<string, number>();\n const stack = new Set<string>();\n\n const dfsDepth = (node: string): number => {\n if (memo.has(node)) return memo.get(node)!;\n if (stack.has(node)) return 0; // break cycles\n\n stack.add(node);\n let maxDepth = 0;\n\n for (const neighbor of graph.outNeighbors(node)) {\n const neighborDepth = dfsDepth(neighbor);\n maxDepth = Math.max(maxDepth, 1 + neighborDepth);\n }\n\n stack.delete(node);\n memo.set(node, maxDepth);\n return maxDepth;\n };\n\n return dfsDepth(elementId);\n }\n\n /**\n * Group dependencies by layer (requires model)\n */\n getDependencyLayers(elementId: string): Record<string, string[]> {\n if (!this.model) return {};\n\n const byLayer: Record<string, string[]> = {};\n const dependencies = this.traceDependencies(elementId, TraceDirection.BOTH);\n\n for (const depId of dependencies) {\n const element = this.model.getElementById(depId);\n if (!element || !element.layer) continue;\n\n if (!byLayer[element.layer]) {\n byLayer[element.layer] = [];\n }\n byLayer[element.layer].push(depId);\n }\n\n return byLayer;\n }\n\n /**\n * Find elements with no references (requires model)\n */\n getOrphanedElements(): Element[] {\n if (!this.model) return [];\n\n const graph = this.getGraph();\n const orphaned: Element[] = [];\n\n for (const layer of this.model.layers.values()) {\n for (const element of layer.elements.values()) {\n const nodeKey = element.path || element.id;\n if (!graph.hasNode(nodeKey)) {\n orphaned.push(element);\n } else if (graph.degree(nodeKey) === 0) {\n orphaned.push(element);\n }\n }\n }\n\n return orphaned;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["TraceDirection"]
7
7
  }