@documentation-robotics/cli 0.1.0 → 0.1.5

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 +206 -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 +155 -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 +37 -13
  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
@@ -0,0 +1,115 @@
1
+ import { RELATIONSHIPS_BY_SOURCE } from "../../../generated/relationship-index.js";
2
+ import { getAllLayers } from "../../../generated/layer-registry.js";
3
+ const DENSITY_TARGETS = {
4
+ structural: [2, 4],
5
+ // Entities, components
6
+ behavioral: [3, 5],
7
+ // Processes, services
8
+ enumeration: [1, 2],
9
+ // States, values
10
+ reference: [0, 1]
11
+ // Metadata, tags
12
+ };
13
+ class BalanceAssessor {
14
+ assessmentCache = null;
15
+ /**
16
+ * Assess balance for all layers
17
+ */
18
+ assessAll() {
19
+ if (this.assessmentCache !== null)
20
+ return this.assessmentCache;
21
+ const layers = getAllLayers(), assessments = [];
22
+ for (const layer of layers) {
23
+ const layerAssessments = this.assessLayer(layer);
24
+ assessments.push(...layerAssessments);
25
+ }
26
+ return this.assessmentCache = assessments, assessments;
27
+ }
28
+ /**
29
+ * Assess balance for a single layer
30
+ */
31
+ assessLayer(layer) {
32
+ const assessments = [];
33
+ for (const nodeType of layer.nodeTypes) {
34
+ const assessment = this.assessNodeType(nodeType, layer.id);
35
+ assessments.push(assessment);
36
+ }
37
+ return assessments;
38
+ }
39
+ /**
40
+ * Assess balance for a single node type
41
+ */
42
+ assessNodeType(nodeType, layerId) {
43
+ const category = this.classifyNodeType(nodeType), currentCount = this.getRelationshipCount(nodeType), targetRange = DENSITY_TARGETS[category], status = this.determineStatus(currentCount, targetRange), recommendation = this.generateRecommendation(nodeType, category, currentCount, targetRange, status);
44
+ return {
45
+ nodeType,
46
+ layer: layerId,
47
+ category,
48
+ currentCount,
49
+ targetRange,
50
+ status,
51
+ recommendation
52
+ };
53
+ }
54
+ /**
55
+ * Classify node type into category
56
+ *
57
+ * IMPORTANT: Categories are checked in precedence order:
58
+ * 1. Enumeration (most specific - uses endsWith)
59
+ * 2. Structural (uses includes - may match substrings)
60
+ * 3. Behavioral (uses includes - may match substrings)
61
+ * 4. Reference (default)
62
+ *
63
+ * The ordering matters because includes() can match substrings.
64
+ * For example, "businessservice" contains "service" (structural)
65
+ * but is behavioral by nature. The current implementation favors
66
+ * structural classification in such cases.
67
+ */
68
+ classifyNodeType(specNodeId) {
69
+ const type = specNodeId.split(".")[1] || "";
70
+ return type ? type.endsWith("level") || type.endsWith("type") || type.endsWith("status") || type.endsWith("priority") || type.endsWith("scope") || type.endsWith("action") || type.endsWith("category") || type.endsWith("format") ? "enumeration" : type.includes("component") || type.includes("container") || type.includes("service") || type.includes("module") || type.includes("collaboration") || type.includes("interface") || type.includes("device") || type.includes("node") || type.includes("artifact") ? "structural" : type.includes("process") || type.includes("operation") || type.includes("event") || type.includes("flow") || type.includes("interaction") || type.includes("function") || type.includes("trigger") ? "behavioral" : "reference" : (console.warn(`Warning: Could not extract type from specNodeId '${specNodeId}', defaulting to 'reference' classification`), "reference");
71
+ }
72
+ /**
73
+ * Get relationship count for node type
74
+ */
75
+ getRelationshipCount(nodeType) {
76
+ return (RELATIONSHIPS_BY_SOURCE.get(nodeType) || []).length;
77
+ }
78
+ /**
79
+ * Determine balance status
80
+ */
81
+ determineStatus(count, targetRange) {
82
+ const [min, max] = targetRange;
83
+ return count < min ? "under" : count > max ? "over" : "balanced";
84
+ }
85
+ /**
86
+ * Generate recommendation
87
+ */
88
+ generateRecommendation(nodeType, category, currentCount, targetRange, status) {
89
+ const [min, max] = targetRange, typeName = nodeType.split(".").pop() || nodeType;
90
+ if (status === "under") {
91
+ const needed = min - currentCount;
92
+ return `Add ${needed} relationship${needed > 1 ? "s" : ""} to ${typeName} (${category} type) to reach minimum target`;
93
+ }
94
+ if (status === "over") {
95
+ const excess = currentCount - max;
96
+ return `Consider removing ${excess} relationship${excess > 1 ? "s" : ""} from ${typeName} or reviewing ${category} type classification`;
97
+ }
98
+ }
99
+ /**
100
+ * Get assessments by status
101
+ */
102
+ assessByStatus(status) {
103
+ return this.assessAll().filter((a) => a.status === status);
104
+ }
105
+ /**
106
+ * Get assessments by category
107
+ */
108
+ assessByCategory(category) {
109
+ return this.assessAll().filter((a) => a.category === category);
110
+ }
111
+ }
112
+ export {
113
+ BalanceAssessor
114
+ };
115
+ //# sourceMappingURL=balance-assessor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/analysis/balance-assessor.ts"],
4
+ "sourcesContent": ["/**\n * Balance Assessor - Assesses relationship density balance\n *\n * Applies heuristics to determine if node types have appropriate\n * numbers of relationships based on their category:\n * - Structural (2-4 relationships): entities, components\n * - Behavioral (3-5 relationships): processes, services\n * - Enumeration (1-2 relationships): states, values\n * - Reference (0-1 relationships): metadata, tags\n */\n\nimport { RELATIONSHIPS_BY_SOURCE } from \"../../../generated/relationship-index.js\";\nimport {\n getAllLayers,\n type LayerMetadata,\n} from \"../../../generated/layer-registry.js\";\nimport type { BalanceAssessment } from \"../../types.js\";\n\n/**\n * Density targets for different node type categories\n */\nconst DENSITY_TARGETS: Record<string, [number, number]> = {\n structural: [2, 4], // Entities, components\n behavioral: [3, 5], // Processes, services\n enumeration: [1, 2], // States, values\n reference: [0, 1], // Metadata, tags\n};\n\n/**\n * Balance assessor for relationship density\n */\nexport class BalanceAssessor {\n private assessmentCache: BalanceAssessment[] | null = null;\n\n /**\n * Assess balance for all layers\n */\n assessAll(): BalanceAssessment[] {\n if (this.assessmentCache !== null) {\n return this.assessmentCache;\n }\n\n const layers = getAllLayers();\n const assessments: BalanceAssessment[] = [];\n\n for (const layer of layers) {\n const layerAssessments = this.assessLayer(layer);\n assessments.push(...layerAssessments);\n }\n\n this.assessmentCache = assessments;\n return assessments;\n }\n\n /**\n * Assess balance for a single layer\n */\n assessLayer(layer: LayerMetadata): BalanceAssessment[] {\n const assessments: BalanceAssessment[] = [];\n\n for (const nodeType of layer.nodeTypes) {\n const assessment = this.assessNodeType(nodeType, layer.id);\n assessments.push(assessment);\n }\n\n return assessments;\n }\n\n /**\n * Assess balance for a single node type\n */\n private assessNodeType(\n nodeType: string,\n layerId: string\n ): BalanceAssessment {\n const category = this.classifyNodeType(nodeType);\n const currentCount = this.getRelationshipCount(nodeType);\n const targetRange = DENSITY_TARGETS[category];\n const status = this.determineStatus(currentCount, targetRange);\n const recommendation = this.generateRecommendation(\n nodeType,\n category,\n currentCount,\n targetRange,\n status\n );\n\n return {\n nodeType,\n layer: layerId,\n category,\n currentCount,\n targetRange,\n status,\n recommendation,\n };\n }\n\n /**\n * Classify node type into category\n *\n * IMPORTANT: Categories are checked in precedence order:\n * 1. Enumeration (most specific - uses endsWith)\n * 2. Structural (uses includes - may match substrings)\n * 3. Behavioral (uses includes - may match substrings)\n * 4. Reference (default)\n *\n * The ordering matters because includes() can match substrings.\n * For example, \"businessservice\" contains \"service\" (structural)\n * but is behavioral by nature. The current implementation favors\n * structural classification in such cases.\n */\n private classifyNodeType(\n specNodeId: string\n ): \"structural\" | \"behavioral\" | \"enumeration\" | \"reference\" {\n const type = specNodeId.split(\".\")[1] || \"\";\n\n // Warn if type extraction fails (unexpected specNodeId format)\n if (!type) {\n console.warn(`Warning: Could not extract type from specNodeId '${specNodeId}', defaulting to 'reference' classification`);\n return \"reference\";\n }\n\n // Enumeration patterns - checked first (most specific, uses endsWith)\n if (\n type.endsWith(\"level\") ||\n type.endsWith(\"type\") ||\n type.endsWith(\"status\") ||\n type.endsWith(\"priority\") ||\n type.endsWith(\"scope\") ||\n type.endsWith(\"action\") ||\n type.endsWith(\"category\") ||\n type.endsWith(\"format\")\n ) {\n return \"enumeration\";\n }\n\n // Structural patterns - checked second\n // NOTE: Uses includes() which may match substrings (e.g., \"businessservice\" matches \"service\")\n if (\n type.includes(\"component\") ||\n type.includes(\"container\") ||\n type.includes(\"service\") ||\n type.includes(\"module\") ||\n type.includes(\"collaboration\") ||\n type.includes(\"interface\") ||\n type.includes(\"device\") ||\n type.includes(\"node\") ||\n type.includes(\"artifact\")\n ) {\n return \"structural\";\n }\n\n // Behavioral patterns - checked third\n if (\n type.includes(\"process\") ||\n type.includes(\"operation\") ||\n type.includes(\"event\") ||\n type.includes(\"flow\") ||\n type.includes(\"interaction\") ||\n type.includes(\"function\") ||\n type.includes(\"trigger\")\n ) {\n return \"behavioral\";\n }\n\n // Default to reference for unmatched types\n return \"reference\";\n }\n\n /**\n * Get relationship count for node type\n */\n private getRelationshipCount(nodeType: string): number {\n const relationships = RELATIONSHIPS_BY_SOURCE.get(nodeType) || [];\n return relationships.length;\n }\n\n /**\n * Determine balance status\n */\n private determineStatus(\n count: number,\n targetRange: [number, number]\n ): \"under\" | \"balanced\" | \"over\" {\n const [min, max] = targetRange;\n\n if (count < min) {\n return \"under\";\n }\n if (count > max) {\n return \"over\";\n }\n return \"balanced\";\n }\n\n /**\n * Generate recommendation\n */\n private generateRecommendation(\n nodeType: string,\n category: string,\n currentCount: number,\n targetRange: [number, number],\n status: \"under\" | \"balanced\" | \"over\"\n ): string | undefined {\n const [min, max] = targetRange;\n const typeName = nodeType.split(\".\").pop() || nodeType;\n\n if (status === \"under\") {\n const needed = min - currentCount;\n return `Add ${needed} relationship${needed > 1 ? \"s\" : \"\"} to ${typeName} (${category} type) to reach minimum target`;\n }\n\n if (status === \"over\") {\n const excess = currentCount - max;\n return `Consider removing ${excess} relationship${excess > 1 ? \"s\" : \"\"} from ${typeName} or reviewing ${category} type classification`;\n }\n\n return undefined;\n }\n\n /**\n * Get assessments by status\n */\n assessByStatus(\n status: \"under\" | \"balanced\" | \"over\"\n ): BalanceAssessment[] {\n const all = this.assessAll();\n return all.filter((a) => a.status === status);\n }\n\n /**\n * Get assessments by category\n */\n assessByCategory(\n category: \"structural\" | \"behavioral\" | \"enumeration\" | \"reference\"\n ): BalanceAssessment[] {\n const all = this.assessAll();\n return all.filter((a) => a.category === category);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,99 @@
1
+ import { RELATIONSHIPS_BY_SOURCE } from "../../../generated/relationship-index.js";
2
+ import { getAllLayers } from "../../../generated/layer-registry.js";
3
+ import { LAYER_TEMPLATES } from "./layer-templates.js";
4
+ import { createPercentage } from "../../types.js";
5
+ class CoverageAnalyzer {
6
+ catalog;
7
+ constructor(catalog) {
8
+ this.catalog = catalog;
9
+ }
10
+ /**
11
+ * Analyze coverage for all layers
12
+ * @returns Result object indicating success/partial/failure with complete flag
13
+ */
14
+ async analyzeAll() {
15
+ const layers = getAllLayers(), results = [], errors = [];
16
+ for (const layer of layers)
17
+ try {
18
+ const metrics = await this.analyzeLayer(layer);
19
+ results.push(metrics);
20
+ } catch (error) {
21
+ errors.push({
22
+ layer: layer.id,
23
+ error: error instanceof Error ? error : new Error(String(error))
24
+ });
25
+ }
26
+ if (results.length === 0 && errors.length > 0)
27
+ throw errors[0].error;
28
+ if (errors.length > 0 && results.length > 0) {
29
+ console.error(`
30
+ \u26A0\uFE0F Warning: Coverage analysis failed for ${errors.length} layer(s):`);
31
+ for (const { layer, error } of errors)
32
+ console.error(` - ${layer}: ${error.message}`);
33
+ console.error(`
34
+ Successfully analyzed ${results.length}/${layers.length} layers.
35
+ `);
36
+ }
37
+ return {
38
+ results,
39
+ failures: errors,
40
+ isComplete: errors.length === 0
41
+ };
42
+ }
43
+ /**
44
+ * Analyze coverage for a single layer
45
+ */
46
+ async analyzeLayer(layer) {
47
+ const nodeTypes = layer.nodeTypes, nodeTypeCount = nodeTypes.length, relationshipCounts = /* @__PURE__ */ new Map(), usedPredicatesSet = /* @__PURE__ */ new Set();
48
+ for (const nodeType of nodeTypes) {
49
+ const relationships = RELATIONSHIPS_BY_SOURCE.get(nodeType) || [];
50
+ relationshipCounts.set(nodeType, relationships.length);
51
+ for (const rel of relationships)
52
+ usedPredicatesSet.add(rel.predicate);
53
+ }
54
+ const relationshipCount = Array.from(relationshipCounts.values()).reduce((sum, count) => sum + count, 0), isolatedNodeTypes = nodeTypes.filter((type) => (relationshipCounts.get(type) || 0) === 0), isolationPercentage = createPercentage(nodeTypeCount > 0 ? isolatedNodeTypes.length / nodeTypeCount * 100 : 0), availablePredicates = await this.getAvailablePredicatesForLayer(layer.id), availablePredicateSet = new Set(availablePredicates), usedPredicates = Array.from(usedPredicatesSet).filter((p) => availablePredicateSet.has(p)), utilizationPercentage = createPercentage(availablePredicates.length > 0 ? usedPredicates.length / availablePredicates.length * 100 : 0), relationshipsPerNodeType = nodeTypeCount > 0 ? relationshipCount / nodeTypeCount : 0, standardAlignment = await this.analyzeStandardAlignment(layer);
55
+ return {
56
+ layer: layer.id,
57
+ nodeTypeCount,
58
+ relationshipCount,
59
+ interLayerRelationshipCount: 0,
60
+ isolatedNodeTypes,
61
+ isolationPercentage,
62
+ availablePredicates,
63
+ usedPredicates,
64
+ utilizationPercentage,
65
+ relationshipsPerNodeType,
66
+ standardAlignment
67
+ };
68
+ }
69
+ /**
70
+ * Get available predicates for a layer
71
+ */
72
+ async getAvailablePredicatesForLayer(layerId) {
73
+ return this.catalog.getTypesForLayer(layerId).map((rt) => rt.predicate);
74
+ }
75
+ /**
76
+ * Analyze standard alignment for ArchiMate layers
77
+ */
78
+ async analyzeStandardAlignment(layer) {
79
+ if (!layer.inspiredBy || layer.inspiredBy.standard !== "ArchiMate 3.2")
80
+ return;
81
+ const expectedPatterns = this.getArchimateExpectedPatterns(layer.id);
82
+ return {
83
+ standard: layer.inspiredBy.standard,
84
+ expectedRelationships: expectedPatterns.length,
85
+ missingFromStandard: expectedPatterns
86
+ };
87
+ }
88
+ /**
89
+ * Get expected ArchiMate relationship patterns for a layer
90
+ */
91
+ getArchimateExpectedPatterns(layerId) {
92
+ const template = LAYER_TEMPLATES.find((t) => t.layer === layerId);
93
+ return template ? template.patterns.map((p) => `${p.sourcePattern}\u2192${p.predicate}\u2192${p.destinationPattern}`) : [];
94
+ }
95
+ }
96
+ export {
97
+ CoverageAnalyzer
98
+ };
99
+ //# sourceMappingURL=coverage-analyzer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/analysis/coverage-analyzer.ts"],
4
+ "sourcesContent": ["/**\n * Coverage Analyzer - Computes relationship coverage metrics\n *\n * Analyzes:\n * - Node isolation (node types with zero relationships)\n * - Predicate utilization (available vs. used predicates)\n * - Relationship density\n * - Standard alignment validation\n */\n\nimport { RelationshipCatalog } from \"../../../core/relationship-catalog.js\";\nimport { RELATIONSHIPS_BY_SOURCE } from \"../../../generated/relationship-index.js\";\nimport {\n getAllLayers,\n type LayerMetadata,\n} from \"../../../generated/layer-registry.js\";\nimport { LAYER_TEMPLATES } from \"./layer-templates.js\";\nimport type { CoverageMetrics } from \"../../types.js\";\nimport { createPercentage } from \"../../types.js\";\n\n/**\n * Result from coverage analysis indicating success/partial/failure status\n */\nexport interface CoverageAnalysisResult {\n /** Metrics for successfully analyzed layers */\n results: CoverageMetrics[];\n /** Failures encountered during analysis (if any) */\n failures: Array<{ layer: string; error: Error }>;\n /** Whether analysis completed for all layers */\n isComplete: boolean;\n}\n\n/**\n * Coverage analyzer for relationship metrics\n */\nexport class CoverageAnalyzer {\n constructor(private catalog: RelationshipCatalog) {}\n\n /**\n * Analyze coverage for all layers\n * @returns Result object indicating success/partial/failure with complete flag\n */\n async analyzeAll(): Promise<CoverageAnalysisResult> {\n const layers = getAllLayers();\n const results: CoverageMetrics[] = [];\n const errors: Array<{ layer: string; error: Error }> = [];\n\n for (const layer of layers) {\n try {\n const metrics = await this.analyzeLayer(layer);\n results.push(metrics);\n } catch (error) {\n errors.push({\n layer: layer.id,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n }\n\n // If all layers failed, throw the first error\n if (results.length === 0 && errors.length > 0) {\n throw errors[0].error;\n }\n\n // Report partial failures to user\n if (errors.length > 0 && results.length > 0) {\n console.error(\n `\\n\u26A0\uFE0F Warning: Coverage analysis failed for ${errors.length} layer(s):`\n );\n for (const { layer, error } of errors) {\n console.error(` - ${layer}: ${error.message}`);\n }\n console.error(\n `\\nSuccessfully analyzed ${results.length}/${layers.length} layers.\\n`\n );\n }\n\n return {\n results,\n failures: errors,\n isComplete: errors.length === 0,\n };\n }\n\n /**\n * Analyze coverage for a single layer\n */\n async analyzeLayer(layer: LayerMetadata): Promise<CoverageMetrics> {\n const nodeTypes = layer.nodeTypes;\n const nodeTypeCount = nodeTypes.length;\n\n // Count relationships per node type\n const relationshipCounts = new Map<string, number>();\n const usedPredicatesSet = new Set<string>();\n\n for (const nodeType of nodeTypes) {\n const relationships = RELATIONSHIPS_BY_SOURCE.get(nodeType) || [];\n relationshipCounts.set(nodeType, relationships.length);\n\n // Track used predicates\n for (const rel of relationships) {\n usedPredicatesSet.add(rel.predicate);\n }\n }\n\n // Calculate total relationships\n const relationshipCount = Array.from(relationshipCounts.values()).reduce(\n (sum, count) => sum + count,\n 0\n );\n\n // Identify isolated node types (zero relationships)\n const isolatedNodeTypes = nodeTypes.filter(\n (type) => (relationshipCounts.get(type) || 0) === 0\n );\n const isolationPercentage = createPercentage(\n nodeTypeCount > 0 ? (isolatedNodeTypes.length / nodeTypeCount) * 100 : 0\n );\n\n // Get available predicates for this layer\n const availablePredicates = await this.getAvailablePredicatesForLayer(\n layer.id\n );\n // Filter used predicates to only include those defined in relationship schemas for this layer\n // This handles cases where relationship index contains predicates not yet formalized in schemas\n const availablePredicateSet = new Set(availablePredicates);\n const usedPredicates = Array.from(usedPredicatesSet).filter(\n (p) => availablePredicateSet.has(p)\n );\n const utilizationPercentage = createPercentage(\n availablePredicates.length > 0\n ? (usedPredicates.length / availablePredicates.length) * 100\n : 0\n );\n\n // Calculate density\n const relationshipsPerNodeType =\n nodeTypeCount > 0 ? relationshipCount / nodeTypeCount : 0;\n\n // Standard alignment (for ArchiMate layers)\n const standardAlignment = await this.analyzeStandardAlignment(layer);\n\n return {\n layer: layer.id,\n nodeTypeCount,\n relationshipCount,\n interLayerRelationshipCount: 0,\n isolatedNodeTypes,\n isolationPercentage,\n availablePredicates,\n usedPredicates,\n utilizationPercentage,\n relationshipsPerNodeType,\n standardAlignment,\n };\n }\n\n /**\n * Get available predicates for a layer\n */\n private async getAvailablePredicatesForLayer(\n layerId: string\n ): Promise<string[]> {\n const relationshipTypes = this.catalog.getTypesForLayer(layerId);\n return relationshipTypes.map((rt) => rt.predicate);\n }\n\n /**\n * Analyze standard alignment for ArchiMate layers\n */\n private async analyzeStandardAlignment(\n layer: LayerMetadata\n ): Promise<CoverageMetrics[\"standardAlignment\"] | undefined> {\n if (!layer.inspiredBy) {\n return undefined;\n }\n\n // Check if this is an ArchiMate layer\n if (layer.inspiredBy.standard !== \"ArchiMate 3.2\") {\n return undefined;\n }\n\n // ArchiMate 3.2 expected relationship patterns\n const expectedPatterns = this.getArchimateExpectedPatterns(layer.id);\n\n return {\n standard: layer.inspiredBy.standard,\n expectedRelationships: expectedPatterns.length,\n missingFromStandard: expectedPatterns,\n };\n }\n\n /**\n * Get expected ArchiMate relationship patterns for a layer\n */\n private getArchimateExpectedPatterns(layerId: string): string[] {\n const template = LAYER_TEMPLATES.find((t) => t.layer === layerId);\n if (!template) {\n return [];\n }\n\n return template.patterns.map(\n (p) => `${p.sourcePattern}\u2192${p.predicate}\u2192${p.destinationPattern}`\n );\n }\n}\n"],
5
+ "mappings": "AAWA,SAAS,+BAA+B;AACxC,SACE,oBAEK;AACP,SAAS,uBAAuB;AAEhC,SAAS,wBAAwB;AAiB3B,MAAO,iBAAgB;EACP;EAApB,YAAoB,SAA4B;AAA5B,SAAA,UAAA;EAA+B;;;;;EAMnD,MAAM,aAAU;AACd,UAAM,SAAS,aAAY,GACrB,UAA6B,CAAA,GAC7B,SAAiD,CAAA;AAEvD,eAAW,SAAS;AAClB,UAAI;AACF,cAAM,UAAU,MAAM,KAAK,aAAa,KAAK;AAC7C,gBAAQ,KAAK,OAAO;MACtB,SAAS,OAAO;AACd,eAAO,KAAK;UACV,OAAO,MAAM;UACb,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;SAChE;MACH;AAIF,QAAI,QAAQ,WAAW,KAAK,OAAO,SAAS;AAC1C,YAAM,OAAO,CAAC,EAAE;AAIlB,QAAI,OAAO,SAAS,KAAK,QAAQ,SAAS,GAAG;AAC3C,cAAQ,MACN;sDAA+C,OAAO,MAAM,YAAY;AAE1E,iBAAW,EAAE,OAAO,MAAK,KAAM;AAC7B,gBAAQ,MAAM,OAAO,KAAK,KAAK,MAAM,OAAO,EAAE;AAEhD,cAAQ,MACN;wBAA2B,QAAQ,MAAM,IAAI,OAAO,MAAM;CAAY;IAE1E;AAEA,WAAO;MACL;MACA,UAAU;MACV,YAAY,OAAO,WAAW;;EAElC;;;;EAKA,MAAM,aAAa,OAAoB;AACrC,UAAM,YAAY,MAAM,WAClB,gBAAgB,UAAU,QAG1B,qBAAqB,oBAAI,IAAG,GAC5B,oBAAoB,oBAAI,IAAG;AAEjC,eAAW,YAAY,WAAW;AAChC,YAAM,gBAAgB,wBAAwB,IAAI,QAAQ,KAAK,CAAA;AAC/D,yBAAmB,IAAI,UAAU,cAAc,MAAM;AAGrD,iBAAW,OAAO;AAChB,0BAAkB,IAAI,IAAI,SAAS;IAEvC;AAGA,UAAM,oBAAoB,MAAM,KAAK,mBAAmB,OAAM,CAAE,EAAE,OAChE,CAAC,KAAK,UAAU,MAAM,OACtB,CAAC,GAIG,oBAAoB,UAAU,OAClC,CAAC,UAAU,mBAAmB,IAAI,IAAI,KAAK,OAAO,CAAC,GAE/C,sBAAsB,iBAC1B,gBAAgB,IAAK,kBAAkB,SAAS,gBAAiB,MAAM,CAAC,GAIpE,sBAAsB,MAAM,KAAK,+BACrC,MAAM,EAAE,GAIJ,wBAAwB,IAAI,IAAI,mBAAmB,GACnD,iBAAiB,MAAM,KAAK,iBAAiB,EAAE,OACnD,CAAC,MAAM,sBAAsB,IAAI,CAAC,CAAC,GAE/B,wBAAwB,iBAC5B,oBAAoB,SAAS,IACxB,eAAe,SAAS,oBAAoB,SAAU,MACvD,CAAC,GAID,2BACJ,gBAAgB,IAAI,oBAAoB,gBAAgB,GAGpD,oBAAoB,MAAM,KAAK,yBAAyB,KAAK;AAEnE,WAAO;MACL,OAAO,MAAM;MACb;MACA;MACA,6BAA6B;MAC7B;MACA;MACA;MACA;MACA;MACA;MACA;;EAEJ;;;;EAKQ,MAAM,+BACZ,SAAe;AAGf,WAD0B,KAAK,QAAQ,iBAAiB,OAAO,EACtC,IAAI,CAAC,OAAO,GAAG,SAAS;EACnD;;;;EAKQ,MAAM,yBACZ,OAAoB;AAOpB,QALI,CAAC,MAAM,cAKP,MAAM,WAAW,aAAa;AAChC;AAIF,UAAM,mBAAmB,KAAK,6BAA6B,MAAM,EAAE;AAEnE,WAAO;MACL,UAAU,MAAM,WAAW;MAC3B,uBAAuB,iBAAiB;MACxC,qBAAqB;;EAEzB;;;;EAKQ,6BAA6B,SAAe;AAClD,UAAM,WAAW,gBAAgB,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO;AAChE,WAAK,WAIE,SAAS,SAAS,IACvB,CAAC,MAAM,GAAG,EAAE,aAAa,SAAI,EAAE,SAAS,SAAI,EAAE,kBAAkB,EAAE,IAJ3D,CAAA;EAMX;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,95 @@
1
+ import { RELATIONSHIPS } from "../../../generated/relationship-index.js";
2
+ import { duplicateImpactScore } from "../../types.js";
3
+ class DuplicateDetector {
4
+ catalog;
5
+ duplicateCache = null;
6
+ constructor(catalog) {
7
+ this.catalog = catalog;
8
+ }
9
+ /**
10
+ * Detect all duplicate candidates
11
+ */
12
+ detectDuplicates() {
13
+ if (this.duplicateCache !== null)
14
+ return this.duplicateCache;
15
+ const candidates = [], relationshipsByEndpoints = /* @__PURE__ */ new Map();
16
+ for (const rel of RELATIONSHIPS) {
17
+ const key = `${rel.sourceSpecNodeId}:${rel.destinationSpecNodeId}`, group = relationshipsByEndpoints.get(key) || [];
18
+ group.push(rel), relationshipsByEndpoints.set(key, group);
19
+ }
20
+ for (const [_, group] of relationshipsByEndpoints)
21
+ if (!(group.length < 2))
22
+ for (let i = 0; i < group.length; i++)
23
+ for (let j = i + 1; j < group.length; j++) {
24
+ const candidate = this.checkDuplicatePair(group[i], group[j]);
25
+ candidate && candidates.push(candidate);
26
+ }
27
+ return this.duplicateCache = candidates, candidates;
28
+ }
29
+ /**
30
+ * Check if two relationships are semantic duplicates
31
+ */
32
+ checkDuplicatePair(rel1, rel2) {
33
+ const pred1 = this.catalog.getTypeByPredicate(rel1.predicate), pred2 = this.catalog.getTypeByPredicate(rel2.predicate);
34
+ if (!pred1 || !pred2)
35
+ return pred1 || console.warn(`[DuplicateDetector] Unknown predicate not found in catalog: ${rel1.predicate} (relationship: ${rel1.id})`), pred2 || console.warn(`[DuplicateDetector] Unknown predicate not found in catalog: ${rel2.predicate} (relationship: ${rel2.id})`), null;
36
+ if (pred1.category === pred2.category) {
37
+ const confidence = this.assessConfidence(pred1, pred2), reason = this.buildReason(pred1, pred2), impactScore = duplicateImpactScore(confidence);
38
+ return {
39
+ relationships: [rel1.id, rel2.id],
40
+ predicates: [rel1.predicate, rel2.predicate],
41
+ sourceNodeType: rel1.sourceSpecNodeId,
42
+ destinationNodeType: rel1.destinationSpecNodeId,
43
+ reason,
44
+ confidence,
45
+ impactScore,
46
+ alignmentScore: 100 - impactScore
47
+ };
48
+ }
49
+ if (pred1.inversePredicate === pred2.predicate || pred2.inversePredicate === pred1.predicate) {
50
+ const impactScore = duplicateImpactScore("high");
51
+ return {
52
+ relationships: [rel1.id, rel2.id],
53
+ predicates: [rel1.predicate, rel2.predicate],
54
+ sourceNodeType: rel1.sourceSpecNodeId,
55
+ destinationNodeType: rel1.destinationSpecNodeId,
56
+ reason: "Predicates are inverses of each other",
57
+ confidence: "high",
58
+ impactScore,
59
+ alignmentScore: 100 - impactScore
60
+ };
61
+ }
62
+ return null;
63
+ }
64
+ /**
65
+ * Assess confidence level of duplicate detection
66
+ */
67
+ assessConfidence(pred1, pred2) {
68
+ return !pred1 || !pred2 ? "low" : pred1.category === pred2.category && pred1.semantics.transitivity === pred2.semantics.transitivity && pred1.semantics.symmetry === pred2.semantics.symmetry ? "high" : pred1.category === pred2.category ? "medium" : "low";
69
+ }
70
+ /**
71
+ * Build reason explanation for duplicate detection
72
+ */
73
+ buildReason(pred1, pred2) {
74
+ if (!pred1 || !pred2)
75
+ return "Unknown";
76
+ const parts = [];
77
+ return pred1.category === pred2.category && parts.push(`Both predicates in "${pred1.category}" category`), pred1.semantics.transitivity && pred2.semantics.transitivity && parts.push("both transitive"), pred1.semantics.symmetry && pred2.semantics.symmetry && parts.push("both symmetric"), parts.join(", ");
78
+ }
79
+ /**
80
+ * Get duplicate candidates by layer
81
+ */
82
+ detectDuplicatesByLayer(layerId) {
83
+ return this.detectDuplicates().filter((d) => d.sourceNodeType.startsWith(`${layerId}.`));
84
+ }
85
+ /**
86
+ * Get duplicate candidates by confidence level
87
+ */
88
+ detectDuplicatesByConfidence(confidence) {
89
+ return this.detectDuplicates().filter((d) => d.confidence === confidence);
90
+ }
91
+ }
92
+ export {
93
+ DuplicateDetector
94
+ };
95
+ //# sourceMappingURL=duplicate-detector.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/analysis/duplicate-detector.ts"],
4
+ "sourcesContent": ["/**\n * Duplicate Detector - Identifies semantic duplicate relationships\n *\n * Detects relationships where multiple predicates express the same\n * architectural meaning using:\n * - Predicate category analysis\n * - Transitivity/symmetry semantics\n * - Source/destination endpoint matching\n */\n\nimport { RelationshipCatalog } from \"../../../core/relationship-catalog.js\";\nimport {\n RELATIONSHIPS,\n type RelationshipSpec,\n} from \"../../../generated/relationship-index.js\";\nimport { duplicateImpactScore, type DuplicateCandidate } from \"../../types.js\";\n\n/**\n * Duplicate detector for semantic relationship overlap\n */\nexport class DuplicateDetector {\n private duplicateCache: DuplicateCandidate[] | null = null;\n\n constructor(private catalog: RelationshipCatalog) {}\n\n /**\n * Detect all duplicate candidates\n */\n detectDuplicates(): DuplicateCandidate[] {\n // Return cached results if available\n if (this.duplicateCache !== null) {\n return this.duplicateCache;\n }\n const candidates: DuplicateCandidate[] = [];\n const relationshipsByEndpoints = new Map<\n string,\n RelationshipSpec[]\n >();\n\n // Group relationships by source+destination\n for (const rel of RELATIONSHIPS) {\n const key = `${rel.sourceSpecNodeId}:${rel.destinationSpecNodeId}`;\n const group = relationshipsByEndpoints.get(key) || [];\n group.push(rel);\n relationshipsByEndpoints.set(key, group);\n }\n\n // Check for predicate overlap within same endpoints\n for (const [_, group] of relationshipsByEndpoints) {\n if (group.length < 2) {\n continue;\n }\n\n // Check all pairs within the group\n for (let i = 0; i < group.length; i++) {\n for (let j = i + 1; j < group.length; j++) {\n const candidate = this.checkDuplicatePair(group[i], group[j]);\n if (candidate) {\n candidates.push(candidate);\n }\n }\n }\n }\n\n // Cache the results\n this.duplicateCache = candidates;\n\n return candidates;\n }\n\n /**\n * Check if two relationships are semantic duplicates\n */\n private checkDuplicatePair(\n rel1: RelationshipSpec,\n rel2: RelationshipSpec\n ): DuplicateCandidate | null {\n const pred1 = this.catalog.getTypeByPredicate(rel1.predicate);\n const pred2 = this.catalog.getTypeByPredicate(rel2.predicate);\n\n if (!pred1 || !pred2) {\n // Log unknown predicates for debugging\n if (!pred1) {\n console.warn(\n `[DuplicateDetector] Unknown predicate not found in catalog: ${rel1.predicate} (relationship: ${rel1.id})`\n );\n }\n if (!pred2) {\n console.warn(\n `[DuplicateDetector] Unknown predicate not found in catalog: ${rel2.predicate} (relationship: ${rel2.id})`\n );\n }\n return null;\n }\n\n // Check if predicates are in the same category\n if (pred1.category === pred2.category) {\n const confidence = this.assessConfidence(pred1, pred2);\n const reason = this.buildReason(pred1, pred2);\n const impactScore = duplicateImpactScore(confidence);\n\n return {\n relationships: [rel1.id, rel2.id],\n predicates: [rel1.predicate, rel2.predicate],\n sourceNodeType: rel1.sourceSpecNodeId,\n destinationNodeType: rel1.destinationSpecNodeId,\n reason,\n confidence,\n impactScore,\n alignmentScore: 100 - impactScore,\n };\n }\n\n // Check for inverse relationships (may indicate redundancy)\n if (\n pred1.inversePredicate === pred2.predicate ||\n pred2.inversePredicate === pred1.predicate\n ) {\n const impactScore = duplicateImpactScore(\"high\");\n return {\n relationships: [rel1.id, rel2.id],\n predicates: [rel1.predicate, rel2.predicate],\n sourceNodeType: rel1.sourceSpecNodeId,\n destinationNodeType: rel1.destinationSpecNodeId,\n reason: \"Predicates are inverses of each other\",\n confidence: \"high\",\n impactScore,\n alignmentScore: 100 - impactScore,\n };\n }\n\n return null;\n }\n\n /**\n * Assess confidence level of duplicate detection\n */\n private assessConfidence(\n pred1: ReturnType<RelationshipCatalog[\"getTypeByPredicate\"]>,\n pred2: ReturnType<RelationshipCatalog[\"getTypeByPredicate\"]>\n ): \"high\" | \"medium\" | \"low\" {\n if (!pred1 || !pred2) {\n return \"low\";\n }\n\n // High confidence: same category + same semantics\n if (\n pred1.category === pred2.category &&\n pred1.semantics.transitivity === pred2.semantics.transitivity &&\n pred1.semantics.symmetry === pred2.semantics.symmetry\n ) {\n return \"high\";\n }\n\n // Medium confidence: same category + different semantics\n if (pred1.category === pred2.category) {\n return \"medium\";\n }\n\n return \"low\";\n }\n\n /**\n * Build reason explanation for duplicate detection\n */\n private buildReason(\n pred1: ReturnType<RelationshipCatalog[\"getTypeByPredicate\"]>,\n pred2: ReturnType<RelationshipCatalog[\"getTypeByPredicate\"]>\n ): string {\n if (!pred1 || !pred2) {\n return \"Unknown\";\n }\n\n const parts: string[] = [];\n\n // Category overlap\n if (pred1.category === pred2.category) {\n parts.push(`Both predicates in \"${pred1.category}\" category`);\n }\n\n // Semantic overlap\n if (pred1.semantics.transitivity && pred2.semantics.transitivity) {\n parts.push(\"both transitive\");\n }\n if (pred1.semantics.symmetry && pred2.semantics.symmetry) {\n parts.push(\"both symmetric\");\n }\n\n return parts.join(\", \");\n }\n\n /**\n * Get duplicate candidates by layer\n */\n detectDuplicatesByLayer(layerId: string): DuplicateCandidate[] {\n const allDuplicates = this.detectDuplicates();\n return allDuplicates.filter((d) =>\n d.sourceNodeType.startsWith(`${layerId}.`)\n );\n }\n\n /**\n * Get duplicate candidates by confidence level\n */\n detectDuplicatesByConfidence(\n confidence: \"high\" | \"medium\" | \"low\"\n ): DuplicateCandidate[] {\n const allDuplicates = this.detectDuplicates();\n return allDuplicates.filter((d) => d.confidence === confidence);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,99 @@
1
+ import { RELATIONSHIPS_BY_SOURCE } from "../../../generated/relationship-index.js";
2
+ import { getAllLayers } from "../../../generated/layer-registry.js";
3
+ import { LAYER_TEMPLATES } from "./layer-templates.js";
4
+ import { gapImpactScore } from "../../types.js";
5
+ class GapAnalyzer {
6
+ /**
7
+ * Analyze gaps for all layers
8
+ */
9
+ analyzeAll() {
10
+ const layers = getAllLayers(), candidates = [];
11
+ for (const layer of layers) {
12
+ const layerGaps = this.analyzeLayer(layer);
13
+ candidates.push(...layerGaps);
14
+ }
15
+ return candidates;
16
+ }
17
+ /**
18
+ * Analyze gaps for a single layer with analysis status
19
+ */
20
+ analyzeLayerWithStatus(layer) {
21
+ const patterns = this.getLayerTemplates(layer);
22
+ if (patterns.length === 0)
23
+ return {
24
+ analyzed: !1,
25
+ gaps: [],
26
+ reason: `No template available for layer '${layer.id}'`
27
+ };
28
+ const candidates = [];
29
+ for (const pattern of patterns) {
30
+ const sourceTypes = this.findMatchingNodeTypes(layer, pattern.sourceType), destinationTypes = this.findMatchingNodeTypes(layer, pattern.destinationType);
31
+ for (const sourceType of sourceTypes)
32
+ for (const destType of destinationTypes)
33
+ if (!this.relationshipExists(sourceType, destType, pattern.predicate)) {
34
+ const priority = this.assessPriority(layer, sourceType), impactScore = gapImpactScore(priority);
35
+ candidates.push({
36
+ sourceNodeType: sourceType,
37
+ destinationNodeType: destType,
38
+ suggestedPredicate: pattern.predicate,
39
+ reason: pattern.reason,
40
+ priority,
41
+ standardReference: pattern.standardReference,
42
+ impactScore,
43
+ alignmentScore: 100 - impactScore
44
+ });
45
+ }
46
+ }
47
+ return {
48
+ analyzed: !0,
49
+ gaps: candidates
50
+ };
51
+ }
52
+ /**
53
+ * Analyze gaps for a single layer (legacy method for backward compatibility)
54
+ */
55
+ analyzeLayer(layer) {
56
+ return this.analyzeLayerWithStatus(layer).gaps;
57
+ }
58
+ /**
59
+ * Get relationship templates for a layer
60
+ */
61
+ getLayerTemplates(layer) {
62
+ const template = LAYER_TEMPLATES.find((t) => t.layer === layer.id);
63
+ return template ? template.patterns.map((p) => ({
64
+ sourceType: p.sourcePattern,
65
+ destinationType: p.destinationPattern,
66
+ predicate: p.predicate,
67
+ reason: p.description,
68
+ standardReference: `${template.standard}`
69
+ })) : [];
70
+ }
71
+ /**
72
+ * Find node types matching a pattern
73
+ */
74
+ findMatchingNodeTypes(layer, pattern) {
75
+ return layer.nodeTypes.filter((nodeType) => {
76
+ const typeName = nodeType.split(".")[1];
77
+ return typeName?.includes(pattern) || typeName === pattern;
78
+ });
79
+ }
80
+ /**
81
+ * Check if a relationship exists
82
+ */
83
+ relationshipExists(sourceType, destType, predicate) {
84
+ return (RELATIONSHIPS_BY_SOURCE.get(sourceType) || []).some((rel) => rel.destinationSpecNodeId === destType && rel.predicate === predicate);
85
+ }
86
+ /**
87
+ * Assess priority of a gap
88
+ */
89
+ assessPriority(layer, sourceType) {
90
+ if (["security", "ux", "navigation"].includes(layer.id))
91
+ return "high";
92
+ const typeName = sourceType.split(".")[1] || "";
93
+ return typeName.includes("component") || typeName.includes("container") || typeName.includes("service") || typeName.includes("module") ? "medium" : "low";
94
+ }
95
+ }
96
+ export {
97
+ GapAnalyzer
98
+ };
99
+ //# sourceMappingURL=gap-analyzer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/analysis/gap-analyzer.ts"],
4
+ "sourcesContent": ["/**\n * Gap Analyzer - Identifies missing relationships based on layer-specific templates\n *\n * Uses standard-inspired templates to identify missing architectural\n * relationships that should exist based on:\n * - ArchiMate 3.2 metamodel patterns (layers 1, 2, 4, 5)\n * - OpenAPI 3.0 operation patterns (layer 6)\n * - NIST SP 800-53 control framework patterns (layer 3)\n * - React and router component patterns (layers 9, 10)\n *\n * Note: Gap detection is heuristic-based and patterns are inspired by these standards\n * and frameworks, not formally compliant implementations of them.\n */\n\nimport { RELATIONSHIPS_BY_SOURCE } from \"../../../generated/relationship-index.js\";\nimport {\n getAllLayers,\n type LayerMetadata,\n} from \"../../../generated/layer-registry.js\";\nimport { LAYER_TEMPLATES } from \"./layer-templates.js\";\nimport { gapImpactScore, type GapCandidate } from \"../../types.js\";\n\n/**\n * Expected relationship pattern template\n */\ninterface RelationshipPattern {\n sourceType: string; // Node type pattern (e.g., \"goal\", \"process\")\n destinationType: string;\n predicate: string;\n reason: string;\n standardReference?: string;\n}\n\n/**\n * Gap analysis result with analysis status\n */\nexport interface GapAnalysisResult {\n analyzed: boolean; // Whether the layer was analyzed\n gaps: GapCandidate[]; // Gap candidates (empty array if analyzed with no gaps, or if not analyzed)\n reason?: string; // Reason for not analyzing (e.g., \"No template available for layer\")\n}\n\n/**\n * Gap analyzer for missing relationships\n */\nexport class GapAnalyzer {\n /**\n * Analyze gaps for all layers\n */\n analyzeAll(): GapCandidate[] {\n const layers = getAllLayers();\n const candidates: GapCandidate[] = [];\n\n for (const layer of layers) {\n const layerGaps = this.analyzeLayer(layer);\n candidates.push(...layerGaps);\n }\n\n return candidates;\n }\n\n /**\n * Analyze gaps for a single layer with analysis status\n */\n analyzeLayerWithStatus(layer: LayerMetadata): GapAnalysisResult {\n const patterns = this.getLayerTemplates(layer);\n\n // Check if layer has templates\n if (patterns.length === 0) {\n return {\n analyzed: false,\n gaps: [],\n reason: `No template available for layer '${layer.id}'`,\n };\n }\n\n const candidates: GapCandidate[] = [];\n\n for (const pattern of patterns) {\n // Find matching node types\n const sourceTypes = this.findMatchingNodeTypes(\n layer,\n pattern.sourceType\n );\n const destinationTypes = this.findMatchingNodeTypes(\n layer,\n pattern.destinationType\n );\n\n // Check for missing relationships\n for (const sourceType of sourceTypes) {\n for (const destType of destinationTypes) {\n const exists = this.relationshipExists(\n sourceType,\n destType,\n pattern.predicate\n );\n\n if (!exists) {\n const priority = this.assessPriority(layer, sourceType);\n const impactScore = gapImpactScore(priority);\n candidates.push({\n sourceNodeType: sourceType,\n destinationNodeType: destType,\n suggestedPredicate: pattern.predicate,\n reason: pattern.reason,\n priority,\n standardReference: pattern.standardReference,\n impactScore,\n alignmentScore: 100 - impactScore,\n });\n }\n }\n }\n }\n\n return {\n analyzed: true,\n gaps: candidates,\n };\n }\n\n /**\n * Analyze gaps for a single layer (legacy method for backward compatibility)\n */\n analyzeLayer(layer: LayerMetadata): GapCandidate[] {\n const result = this.analyzeLayerWithStatus(layer);\n return result.gaps;\n }\n\n /**\n * Get relationship templates for a layer\n */\n private getLayerTemplates(layer: LayerMetadata): RelationshipPattern[] {\n const template = LAYER_TEMPLATES.find((t) => t.layer === layer.id);\n if (!template) {\n return [];\n }\n\n return template.patterns.map((p) => ({\n sourceType: p.sourcePattern,\n destinationType: p.destinationPattern,\n predicate: p.predicate,\n reason: p.description,\n standardReference: `${template.standard}`,\n }));\n }\n\n /**\n * Find node types matching a pattern\n */\n private findMatchingNodeTypes(\n layer: LayerMetadata,\n pattern: string\n ): string[] {\n return layer.nodeTypes.filter((nodeType) => {\n const typeName = nodeType.split(\".\")[1];\n return typeName?.includes(pattern) || typeName === pattern;\n });\n }\n\n /**\n * Check if a relationship exists\n */\n private relationshipExists(\n sourceType: string,\n destType: string,\n predicate: string\n ): boolean {\n const relationships = RELATIONSHIPS_BY_SOURCE.get(sourceType) || [];\n return relationships.some(\n (rel) =>\n rel.destinationSpecNodeId === destType && rel.predicate === predicate\n );\n }\n\n /**\n * Assess priority of a gap\n */\n private assessPriority(\n layer: LayerMetadata,\n sourceType: string\n ): \"high\" | \"medium\" | \"low\" {\n // High priority: zero-relationship layers\n if ([\"security\", \"ux\", \"navigation\"].includes(layer.id)) {\n return \"high\";\n }\n\n // Medium priority: container/composition types\n const typeName = sourceType.split(\".\")[1] || \"\";\n if (\n typeName.includes(\"component\") ||\n typeName.includes(\"container\") ||\n typeName.includes(\"service\") ||\n typeName.includes(\"module\")\n ) {\n return \"medium\";\n }\n\n // Low priority: all other patterns\n return \"low\";\n }\n}\n"],
5
+ "mappings": "AAcA,SAAS,+BAA+B;AACxC,SACE,oBAEK;AACP,SAAS,uBAAuB;AAChC,SAAS,sBAAyC;AAyB5C,MAAO,YAAW;;;;EAItB,aAAU;AACR,UAAM,SAAS,aAAY,GACrB,aAA6B,CAAA;AAEnC,eAAW,SAAS,QAAQ;AAC1B,YAAM,YAAY,KAAK,aAAa,KAAK;AACzC,iBAAW,KAAK,GAAG,SAAS;IAC9B;AAEA,WAAO;EACT;;;;EAKA,uBAAuB,OAAoB;AACzC,UAAM,WAAW,KAAK,kBAAkB,KAAK;AAG7C,QAAI,SAAS,WAAW;AACtB,aAAO;QACL,UAAU;QACV,MAAM,CAAA;QACN,QAAQ,oCAAoC,MAAM,EAAE;;AAIxD,UAAM,aAA6B,CAAA;AAEnC,eAAW,WAAW,UAAU;AAE9B,YAAM,cAAc,KAAK,sBACvB,OACA,QAAQ,UAAU,GAEd,mBAAmB,KAAK,sBAC5B,OACA,QAAQ,eAAe;AAIzB,iBAAW,cAAc;AACvB,mBAAW,YAAY;AAOrB,cAAI,CANW,KAAK,mBAClB,YACA,UACA,QAAQ,SAAS,GAGN;AACX,kBAAM,WAAW,KAAK,eAAe,OAAO,UAAU,GAChD,cAAc,eAAe,QAAQ;AAC3C,uBAAW,KAAK;cACd,gBAAgB;cAChB,qBAAqB;cACrB,oBAAoB,QAAQ;cAC5B,QAAQ,QAAQ;cAChB;cACA,mBAAmB,QAAQ;cAC3B;cACA,gBAAgB,MAAM;aACvB;UACH;IAGN;AAEA,WAAO;MACL,UAAU;MACV,MAAM;;EAEV;;;;EAKA,aAAa,OAAoB;AAE/B,WADe,KAAK,uBAAuB,KAAK,EAClC;EAChB;;;;EAKQ,kBAAkB,OAAoB;AAC5C,UAAM,WAAW,gBAAgB,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM,EAAE;AACjE,WAAK,WAIE,SAAS,SAAS,IAAI,CAAC,OAAO;MACnC,YAAY,EAAE;MACd,iBAAiB,EAAE;MACnB,WAAW,EAAE;MACb,QAAQ,EAAE;MACV,mBAAmB,GAAG,SAAS,QAAQ;MACvC,IATO,CAAA;EAUX;;;;EAKQ,sBACN,OACA,SAAe;AAEf,WAAO,MAAM,UAAU,OAAO,CAAC,aAAY;AACzC,YAAM,WAAW,SAAS,MAAM,GAAG,EAAE,CAAC;AACtC,aAAO,UAAU,SAAS,OAAO,KAAK,aAAa;IACrD,CAAC;EACH;;;;EAKQ,mBACN,YACA,UACA,WAAiB;AAGjB,YADsB,wBAAwB,IAAI,UAAU,KAAK,CAAA,GAC5C,KACnB,CAAC,QACC,IAAI,0BAA0B,YAAY,IAAI,cAAc,SAAS;EAE3E;;;;EAKQ,eACN,OACA,YAAkB;AAGlB,QAAI,CAAC,YAAY,MAAM,YAAY,EAAE,SAAS,MAAM,EAAE;AACpD,aAAO;AAIT,UAAM,WAAW,WAAW,MAAM,GAAG,EAAE,CAAC,KAAK;AAC7C,WACE,SAAS,SAAS,WAAW,KAC7B,SAAS,SAAS,WAAW,KAC7B,SAAS,SAAS,SAAS,KAC3B,SAAS,SAAS,QAAQ,IAEnB,WAIF;EACT;;",
6
+ "names": []
7
+ }