@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,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/graph/relationship-graph.ts"],
4
+ "sourcesContent": ["/**\n * Relationship Graph - Graph analysis wrapper for audit system\n *\n * Builds directed graphs from intra-layer relationships using GraphModel\n * and provides audit-specific graph queries.\n */\n\nimport { GraphModel, type GraphEdge } from \"../../../core/graph-model.js\";\nimport { RELATIONSHIPS } from \"../../../generated/relationship-index.js\";\nimport { getAllLayers } from \"../../../generated/layer-registry.js\";\nimport type { Relationship } from \"../../../core/relationships.js\";\nimport type { Element } from \"../../../core/element.js\";\n\n/**\n * Relationship graph for audit analysis\n */\nexport class RelationshipGraph {\n private graph: GraphModel;\n\n constructor() {\n this.graph = new GraphModel();\n }\n\n /**\n * Build graph from intra-layer relationships\n */\n async build(layerId?: string): Promise<void> {\n this.graph.clear();\n\n // Filter relationships by layer if specified\n const relationships = layerId\n ? RELATIONSHIPS.filter((r) =>\n r.sourceSpecNodeId.startsWith(`${layerId}.`)\n )\n : RELATIONSHIPS;\n\n // Add nodes (node types as graph nodes)\n const nodeTypes = new Set<string>();\n\n // First, collect nodes from relationships\n for (const rel of relationships) {\n nodeTypes.add(rel.sourceSpecNodeId);\n nodeTypes.add(rel.destinationSpecNodeId);\n }\n\n // If building a layer-specific graph, also add all node types from that layer\n // (even if they have no relationships)\n if (layerId) {\n const layers = getAllLayers();\n const layer = layers.find((l) => l.id === layerId);\n if (layer) {\n for (const nodeType of layer.nodeTypes) {\n nodeTypes.add(nodeType);\n }\n }\n }\n\n for (const nodeType of nodeTypes) {\n const [layer, type] = nodeType.split(\".\");\n this.graph.addNode({\n id: nodeType,\n layer: layer || \"unknown\",\n type: type || \"unknown\",\n name: nodeType,\n properties: {},\n });\n }\n\n // Add edges (relationships as graph edges)\n const skippedEdges: Array<{\n relationshipId: string;\n source: string;\n destination: string;\n reason: string;\n }> = [];\n\n for (const rel of relationships) {\n try {\n this.graph.addEdge({\n id: rel.id,\n source: rel.sourceSpecNodeId,\n destination: rel.destinationSpecNodeId,\n predicate: rel.predicate,\n properties: {\n cardinality: rel.cardinality,\n strength: rel.strength,\n required: rel.required,\n },\n });\n } catch (error) {\n // Track data integrity issues - relationships referencing non-existent node types\n const reason = error instanceof Error ? error.message : String(error);\n skippedEdges.push({\n relationshipId: rel.id,\n source: rel.sourceSpecNodeId,\n destination: rel.destinationSpecNodeId,\n reason,\n });\n\n // Log to stderr for visibility\n console.error(\n `\u26A0\uFE0F Data integrity issue: Relationship \"${rel.id}\" references non-existent node type. ${reason}`\n );\n }\n }\n\n // Report summary if any edges were skipped\n if (skippedEdges.length > 0) {\n console.error(\n `\\n\u26A0\uFE0F Warning: ${skippedEdges.length} relationship(s) skipped due to missing node type references.`\n );\n console.error(\n `This indicates data integrity issues in the relationship schemas.`\n );\n console.error(\n `Run 'dr schema relationships' to validate relationship definitions.\\n`\n );\n }\n }\n\n /**\n * Get node count\n */\n getNodeCount(): number {\n return this.graph.getNodeCount();\n }\n\n /**\n * Get edge count\n */\n getEdgeCount(): number {\n return this.graph.getEdgeCount();\n }\n\n /**\n * Get all node types in the graph\n */\n getNodeTypes(): string[] {\n return Array.from(this.graph.nodes.keys());\n }\n\n /**\n * Get outgoing relationships for a node type\n */\n getOutgoingRelationships(nodeType: string): GraphEdge[] {\n return this.graph.getEdgesFrom(nodeType);\n }\n\n /**\n * Get incoming relationships for a node type\n */\n getIncomingRelationships(nodeType: string): GraphEdge[] {\n return this.graph.getEdgesTo(nodeType);\n }\n\n /**\n * Get all relationships for a node type\n */\n getAllRelationships(nodeType: string): GraphEdge[] {\n return [\n ...this.graph.getEdgesFrom(nodeType),\n ...this.graph.getEdgesTo(nodeType),\n ];\n }\n\n /**\n * Find paths between two node types\n */\n findPaths(\n sourceType: string,\n destType: string,\n maxDepth: number = 5\n ): string[][] {\n const paths: string[][] = [];\n const visited = new Set<string>();\n\n const dfs = (current: string, path: string[], depth: number) => {\n if (depth > maxDepth) {\n return;\n }\n\n if (current === destType) {\n paths.push([...path, current]);\n return;\n }\n\n if (visited.has(current)) {\n return;\n }\n\n visited.add(current);\n path.push(current);\n\n const outgoing = this.graph.getEdgesFrom(current);\n for (const edge of outgoing) {\n dfs(edge.destination, [...path], depth + 1);\n }\n\n visited.delete(current);\n };\n\n dfs(sourceType, [], 0);\n return paths;\n }\n\n /**\n * Get neighbors of a node type\n */\n getNeighbors(nodeType: string): string[] {\n const neighbors = new Set<string>();\n\n const outgoing = this.graph.getEdgesFrom(nodeType);\n for (const edge of outgoing) {\n neighbors.add(edge.destination);\n }\n\n const incoming = this.graph.getEdgesTo(nodeType);\n for (const edge of incoming) {\n neighbors.add(edge.source);\n }\n\n return Array.from(neighbors);\n }\n\n /**\n * Get the underlying graph model\n */\n getGraphModel(): GraphModel {\n return this.graph;\n }\n\n /**\n * Build graph from actual model relationship instances and elements.\n * Used by ModelAuditOrchestrator to analyse the project model rather than spec schemas.\n */\n buildFromModel(relationships: Relationship[], elements: Element[]): void {\n this.graph.clear();\n\n // Index elements by both UUID id and path/slug \u2014 relationships store slug paths.\n const elementById = new Map<string, Element>();\n for (const e of elements) {\n elementById.set(e.id, e);\n if (e.path && e.path !== e.id) elementById.set(e.path, e);\n }\n\n // Add one graph node per distinct spec_node_id (using spec_node_id as the node id)\n const specNodeIds = new Set<string>(\n elements.map((e) => e.spec_node_id).filter(Boolean)\n );\n\n for (const specNodeId of specNodeIds) {\n const [layer, type] = specNodeId.split(\".\");\n this.graph.addNode({\n id: specNodeId,\n layer: layer ?? \"unknown\",\n type: type ?? \"unknown\",\n name: specNodeId,\n properties: {},\n });\n }\n\n // Add edges from relationship instances, keyed by source/target spec_node_id\n let edgeCounter = 0;\n for (const rel of relationships) {\n const srcEl = elementById.get(rel.source);\n const dstEl = elementById.get(rel.target);\n if (!srcEl?.spec_node_id || !dstEl?.spec_node_id) continue;\n\n try {\n this.graph.addEdge({\n id: `model-rel-${edgeCounter++}`,\n source: srcEl.spec_node_id,\n destination: dstEl.spec_node_id,\n predicate: rel.predicate,\n properties: rel.properties as Record<string, unknown> | undefined,\n category: rel.category,\n });\n } catch {\n // Silently skip edges where the node wasn't added (shouldn't happen but be safe)\n }\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,49 @@
1
+ const DENSITY_TARGETS = {
2
+ structural: [2, 4],
3
+ behavioral: [3, 5],
4
+ enumeration: [1, 2],
5
+ reference: [0, 1]
6
+ };
7
+ function assessLayerBalance(layerId, elements, intraLayerRels) {
8
+ const assessments = [], elementById = /* @__PURE__ */ new Map();
9
+ for (const e of elements)
10
+ elementById.set(e.id, e), e.path && e.path !== e.id && elementById.set(e.path, e);
11
+ const relCountBySpecNodeId = /* @__PURE__ */ new Map();
12
+ for (const rel of intraLayerRels) {
13
+ const srcEl = elementById.get(rel.source);
14
+ srcEl?.spec_node_id && relCountBySpecNodeId.set(srcEl.spec_node_id, (relCountBySpecNodeId.get(srcEl.spec_node_id) ?? 0) + 1);
15
+ }
16
+ const specNodeIds = new Set(elements.map((e) => e.spec_node_id).filter(Boolean));
17
+ for (const specNodeId of specNodeIds) {
18
+ const category = classifyNodeType(specNodeId), currentCount = relCountBySpecNodeId.get(specNodeId) ?? 0, targetRange = DENSITY_TARGETS[category], [min, max] = targetRange, status = currentCount < min ? "under" : currentCount > max ? "over" : "balanced", recommendation = buildRecommendation(specNodeId, category, currentCount, targetRange, status);
19
+ assessments.push({
20
+ nodeType: specNodeId,
21
+ layer: layerId,
22
+ category,
23
+ currentCount,
24
+ targetRange,
25
+ status,
26
+ recommendation
27
+ });
28
+ }
29
+ return assessments;
30
+ }
31
+ function classifyNodeType(specNodeId) {
32
+ const type = specNodeId.split(".")[1] ?? "";
33
+ return 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";
34
+ }
35
+ function buildRecommendation(specNodeId, category, currentCount, targetRange, status) {
36
+ const [min, max] = targetRange, typeName = specNodeId.split(".").pop() ?? specNodeId;
37
+ if (status === "under") {
38
+ const needed = min - currentCount;
39
+ return `Add ${needed} relationship instance${needed > 1 ? "s" : ""} for ${typeName} (${category} type) to reach minimum target`;
40
+ }
41
+ if (status === "over") {
42
+ const excess = currentCount - max;
43
+ return `Consider removing ${excess} relationship instance${excess > 1 ? "s" : ""} from ${typeName} or reviewing ${category} type classification`;
44
+ }
45
+ }
46
+ export {
47
+ assessLayerBalance
48
+ };
49
+ //# sourceMappingURL=balance-assessor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/model/balance-assessor.ts"],
4
+ "sourcesContent": ["/**\n * Model Balance Assessor - Assesses relationship density balance in model instances\n *\n * Groups relationship instances by source element's spec_node_id and applies\n * the same target-range logic as the spec-based BalanceAssessor.\n */\n\nimport type { Relationship } from \"../../../core/relationships.js\";\nimport type { Element } from \"../../../core/element.js\";\nimport type { BalanceAssessment } from \"../../types.js\";\n\n/**\n * Density targets for different node type categories (matches BalanceAssessor)\n */\nconst DENSITY_TARGETS: Record<string, [number, number]> = {\n structural: [2, 4],\n behavioral: [3, 5],\n enumeration: [1, 2],\n reference: [0, 1],\n};\n\n/**\n * Assess balance for a layer using model instances\n */\nexport function assessLayerBalance(\n layerId: string,\n elements: Element[],\n intraLayerRels: Relationship[]\n): BalanceAssessment[] {\n const assessments: BalanceAssessment[] = [];\n\n // Build count of outgoing intra-layer rels per spec_node_id.\n // Index by both UUID id and path/slug \u2014 relationships store slug paths.\n const elementById = new Map<string, Element>();\n for (const e of elements) {\n elementById.set(e.id, e);\n if (e.path && e.path !== e.id) elementById.set(e.path, e);\n }\n\n const relCountBySpecNodeId = new Map<string, number>();\n for (const rel of intraLayerRels) {\n const srcEl = elementById.get(rel.source);\n if (!srcEl?.spec_node_id) continue;\n relCountBySpecNodeId.set(\n srcEl.spec_node_id,\n (relCountBySpecNodeId.get(srcEl.spec_node_id) ?? 0) + 1\n );\n }\n\n // Assess each distinct spec_node_id present in this layer\n const specNodeIds = new Set<string>(\n elements.map((e) => e.spec_node_id).filter(Boolean)\n );\n\n for (const specNodeId of specNodeIds) {\n const category = classifyNodeType(specNodeId);\n const currentCount = relCountBySpecNodeId.get(specNodeId) ?? 0;\n const targetRange = DENSITY_TARGETS[category];\n const [min, max] = targetRange;\n const status: \"under\" | \"balanced\" | \"over\" =\n currentCount < min ? \"under\" : currentCount > max ? \"over\" : \"balanced\";\n const recommendation = buildRecommendation(\n specNodeId,\n category,\n currentCount,\n targetRange,\n status\n );\n\n assessments.push({\n nodeType: specNodeId,\n layer: layerId,\n category,\n currentCount,\n targetRange,\n status,\n recommendation,\n });\n }\n\n return assessments;\n}\n\nfunction classifyNodeType(\n specNodeId: string\n): \"structural\" | \"behavioral\" | \"enumeration\" | \"reference\" {\n const type = specNodeId.split(\".\")[1] ?? \"\";\n\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 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 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 return \"reference\";\n}\n\nfunction buildRecommendation(\n specNodeId: 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 = specNodeId.split(\".\").pop() ?? specNodeId;\n\n if (status === \"under\") {\n const needed = min - currentCount;\n return `Add ${needed} relationship instance${needed > 1 ? \"s\" : \"\"} for ${typeName} (${category} type) to reach minimum target`;\n }\n if (status === \"over\") {\n const excess = currentCount - max;\n return `Consider removing ${excess} relationship instance${excess > 1 ? \"s\" : \"\"} from ${typeName} or reviewing ${category} type classification`;\n }\n return undefined;\n}\n"],
5
+ "mappings": "AAcA,MAAM,kBAAoD;EACxD,YAAY,CAAC,GAAG,CAAC;EACjB,YAAY,CAAC,GAAG,CAAC;EACjB,aAAa,CAAC,GAAG,CAAC;EAClB,WAAW,CAAC,GAAG,CAAC;;AAMZ,SAAU,mBACd,SACA,UACA,gBAA8B;AAE9B,QAAM,cAAmC,CAAA,GAInC,cAAc,oBAAI,IAAG;AAC3B,aAAW,KAAK;AACd,gBAAY,IAAI,EAAE,IAAI,CAAC,GACnB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAI,YAAY,IAAI,EAAE,MAAM,CAAC;AAG1D,QAAM,uBAAuB,oBAAI,IAAG;AACpC,aAAW,OAAO,gBAAgB;AAChC,UAAM,QAAQ,YAAY,IAAI,IAAI,MAAM;AACxC,IAAK,OAAO,gBACZ,qBAAqB,IACnB,MAAM,eACL,qBAAqB,IAAI,MAAM,YAAY,KAAK,KAAK,CAAC;EAE3D;AAGA,QAAM,cAAc,IAAI,IACtB,SAAS,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,OAAO,CAAC;AAGrD,aAAW,cAAc,aAAa;AACpC,UAAM,WAAW,iBAAiB,UAAU,GACtC,eAAe,qBAAqB,IAAI,UAAU,KAAK,GACvD,cAAc,gBAAgB,QAAQ,GACtC,CAAC,KAAK,GAAG,IAAI,aACb,SACJ,eAAe,MAAM,UAAU,eAAe,MAAM,SAAS,YACzD,iBAAiB,oBACrB,YACA,UACA,cACA,aACA,MAAM;AAGR,gBAAY,KAAK;MACf,UAAU;MACV,OAAO;MACP;MACA;MACA;MACA;MACA;KACD;EACH;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,YAAkB;AAElB,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,CAAC,KAAK;AAEzC,SACE,KAAK,SAAS,OAAO,KACrB,KAAK,SAAS,MAAM,KACpB,KAAK,SAAS,QAAQ,KACtB,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,OAAO,KACrB,KAAK,SAAS,QAAQ,KACtB,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,QAAQ,IAEf,gBAIP,KAAK,SAAS,WAAW,KACzB,KAAK,SAAS,WAAW,KACzB,KAAK,SAAS,SAAS,KACvB,KAAK,SAAS,QAAQ,KACtB,KAAK,SAAS,eAAe,KAC7B,KAAK,SAAS,WAAW,KACzB,KAAK,SAAS,QAAQ,KACtB,KAAK,SAAS,MAAM,KACpB,KAAK,SAAS,UAAU,IAEjB,eAIP,KAAK,SAAS,SAAS,KACvB,KAAK,SAAS,WAAW,KACzB,KAAK,SAAS,OAAO,KACrB,KAAK,SAAS,MAAM,KACpB,KAAK,SAAS,aAAa,KAC3B,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,SAAS,IAEhB,eAGF;AACT;AAEA,SAAS,oBACP,YACA,UACA,cACA,aACA,QAAqC;AAErC,QAAM,CAAC,KAAK,GAAG,IAAI,aACb,WAAW,WAAW,MAAM,GAAG,EAAE,IAAG,KAAM;AAEhD,MAAI,WAAW,SAAS;AACtB,UAAM,SAAS,MAAM;AACrB,WAAO,OAAO,MAAM,yBAAyB,SAAS,IAAI,MAAM,EAAE,QAAQ,QAAQ,KAAK,QAAQ;EACjG;AACA,MAAI,WAAW,QAAQ;AACrB,UAAM,SAAS,eAAe;AAC9B,WAAO,qBAAqB,MAAM,yBAAyB,SAAS,IAAI,MAAM,EAAE,SAAS,QAAQ,iBAAiB,QAAQ;EAC5H;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,34 @@
1
+ import { createPercentage } from "../../types.js";
2
+ function analyzeLayerCoverage(layerId, elements, intraLayerRels, interLayerRels, catalog) {
3
+ const specNodeIds = new Set(elements.map((e) => e.spec_node_id).filter(Boolean)), nodeTypeCount = specNodeIds.size, elementById = /* @__PURE__ */ new Map();
4
+ for (const e of elements)
5
+ elementById.set(e.id, e), e.path && e.path !== e.id && elementById.set(e.path, e);
6
+ const relCountBySpecNodeId = /* @__PURE__ */ new Map(), usedPredicatesSet = /* @__PURE__ */ new Set();
7
+ for (const rel of intraLayerRels) {
8
+ const sourceEl = elementById.get(rel.source);
9
+ sourceEl?.spec_node_id && relCountBySpecNodeId.set(sourceEl.spec_node_id, (relCountBySpecNodeId.get(sourceEl.spec_node_id) ?? 0) + 1), usedPredicatesSet.add(rel.predicate);
10
+ }
11
+ for (const rel of interLayerRels) {
12
+ const sourceEl = elementById.get(rel.source);
13
+ sourceEl?.spec_node_id && relCountBySpecNodeId.set(sourceEl.spec_node_id, (relCountBySpecNodeId.get(sourceEl.spec_node_id) ?? 0) + 1);
14
+ const targetEl = elementById.get(rel.target);
15
+ targetEl?.spec_node_id && relCountBySpecNodeId.set(targetEl.spec_node_id, (relCountBySpecNodeId.get(targetEl.spec_node_id) ?? 0) + 1), usedPredicatesSet.add(rel.predicate);
16
+ }
17
+ const relationshipCount = intraLayerRels.length, interLayerRelationshipCount = interLayerRels.length, isolatedNodeTypes = Array.from(specNodeIds).filter((id) => (relCountBySpecNodeId.get(id) ?? 0) === 0), isolationPercentage = createPercentage(nodeTypeCount > 0 ? isolatedNodeTypes.length / nodeTypeCount * 100 : 0), availablePredicates = catalog.getTypesForLayer(layerId).map((t) => t.predicate), 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;
18
+ return {
19
+ layer: layerId,
20
+ nodeTypeCount,
21
+ relationshipCount,
22
+ interLayerRelationshipCount,
23
+ isolatedNodeTypes,
24
+ isolationPercentage,
25
+ availablePredicates,
26
+ usedPredicates,
27
+ utilizationPercentage,
28
+ relationshipsPerNodeType
29
+ };
30
+ }
31
+ export {
32
+ analyzeLayerCoverage
33
+ };
34
+ //# sourceMappingURL=coverage-analyzer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/model/coverage-analyzer.ts"],
4
+ "sourcesContent": ["/**\n * Model Coverage Analyzer - Coverage metrics from actual model relationship instances\n */\n\nimport type { Relationship } from \"../../../core/relationships.js\";\nimport type { Element } from \"../../../core/element.js\";\nimport { RelationshipCatalog } from \"../../../core/relationship-catalog.js\";\nimport type { CoverageMetrics } from \"../../types.js\";\nimport { createPercentage } from \"../../types.js\";\n\n/**\n * Analyze relationship coverage for a single layer using model instances\n */\nexport function analyzeLayerCoverage(\n layerId: string,\n elements: Element[],\n intraLayerRels: Relationship[],\n interLayerRels: Relationship[],\n catalog: RelationshipCatalog\n): CoverageMetrics {\n // Distinct spec_node_ids present in this layer\n const specNodeIds = new Set<string>(\n elements.map((e) => e.spec_node_id).filter(Boolean)\n );\n const nodeTypeCount = specNodeIds.size;\n\n // Index elements by both UUID id and path/slug \u2014 relationships store slug paths.\n const elementById = new Map<string, Element>();\n for (const e of elements) {\n elementById.set(e.id, e);\n if (e.path && e.path !== e.id) elementById.set(e.path, e);\n }\n\n // Count relationship instances per spec_node_id \u2014 includes both intra and inter-layer\n // relationships for isolation scoring. A node type is only isolated if it participates\n // in no relationships at all (not just intra-layer ones).\n const relCountBySpecNodeId = new Map<string, number>();\n const usedPredicatesSet = new Set<string>();\n\n for (const rel of intraLayerRels) {\n const sourceEl = elementById.get(rel.source);\n if (sourceEl?.spec_node_id) {\n relCountBySpecNodeId.set(\n sourceEl.spec_node_id,\n (relCountBySpecNodeId.get(sourceEl.spec_node_id) ?? 0) + 1\n );\n }\n usedPredicatesSet.add(rel.predicate);\n }\n\n // Cross-layer relationships count toward isolation and predicate utilization.\n // Without this, node types that only participate in cross-layer relationships\n // appear isolated and their predicates don't appear in usedPredicates.\n for (const rel of interLayerRels) {\n const sourceEl = elementById.get(rel.source);\n if (sourceEl?.spec_node_id) {\n relCountBySpecNodeId.set(\n sourceEl.spec_node_id,\n (relCountBySpecNodeId.get(sourceEl.spec_node_id) ?? 0) + 1\n );\n }\n // Also count inbound rels \u2014 a node type targeted by a cross-layer relationship\n // is not isolated, even if it never acts as a source.\n const targetEl = elementById.get(rel.target);\n if (targetEl?.spec_node_id) {\n relCountBySpecNodeId.set(\n targetEl.spec_node_id,\n (relCountBySpecNodeId.get(targetEl.spec_node_id) ?? 0) + 1\n );\n }\n usedPredicatesSet.add(rel.predicate);\n }\n\n const relationshipCount = intraLayerRels.length;\n const interLayerRelationshipCount = interLayerRels.length;\n\n // Isolated: spec_node_ids present in layer with zero relationship instances (intra OR inter)\n const isolatedNodeTypes = Array.from(specNodeIds).filter(\n (id) => (relCountBySpecNodeId.get(id) ?? 0) === 0\n );\n const isolationPercentage = createPercentage(\n nodeTypeCount > 0 ? (isolatedNodeTypes.length / nodeTypeCount) * 100 : 0\n );\n\n // Available predicates for this layer from catalog\n const availablePredicates = catalog\n .getTypesForLayer(layerId)\n .map((t) => t.predicate);\n const availablePredicateSet = new Set(availablePredicates);\n\n // Only count predicates that the catalog defines for this layer\n const usedPredicates = Array.from(usedPredicatesSet).filter((p) =>\n availablePredicateSet.has(p)\n );\n\n const utilizationPercentage = createPercentage(\n availablePredicates.length > 0\n ? (usedPredicates.length / availablePredicates.length) * 100\n : 0\n );\n\n const relationshipsPerNodeType =\n nodeTypeCount > 0 ? relationshipCount / nodeTypeCount : 0;\n\n return {\n layer: layerId,\n nodeTypeCount,\n relationshipCount,\n interLayerRelationshipCount,\n isolatedNodeTypes,\n isolationPercentage,\n availablePredicates,\n usedPredicates,\n utilizationPercentage,\n relationshipsPerNodeType,\n };\n}\n"],
5
+ "mappings": "AAQA,SAAS,wBAAwB;AAK3B,SAAU,qBACd,SACA,UACA,gBACA,gBACA,SAA4B;AAG5B,QAAM,cAAc,IAAI,IACtB,SAAS,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,OAAO,CAAC,GAE/C,gBAAgB,YAAY,MAG5B,cAAc,oBAAI,IAAG;AAC3B,aAAW,KAAK;AACd,gBAAY,IAAI,EAAE,IAAI,CAAC,GACnB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAI,YAAY,IAAI,EAAE,MAAM,CAAC;AAM1D,QAAM,uBAAuB,oBAAI,IAAG,GAC9B,oBAAoB,oBAAI,IAAG;AAEjC,aAAW,OAAO,gBAAgB;AAChC,UAAM,WAAW,YAAY,IAAI,IAAI,MAAM;AAC3C,IAAI,UAAU,gBACZ,qBAAqB,IACnB,SAAS,eACR,qBAAqB,IAAI,SAAS,YAAY,KAAK,KAAK,CAAC,GAG9D,kBAAkB,IAAI,IAAI,SAAS;EACrC;AAKA,aAAW,OAAO,gBAAgB;AAChC,UAAM,WAAW,YAAY,IAAI,IAAI,MAAM;AAC3C,IAAI,UAAU,gBACZ,qBAAqB,IACnB,SAAS,eACR,qBAAqB,IAAI,SAAS,YAAY,KAAK,KAAK,CAAC;AAK9D,UAAM,WAAW,YAAY,IAAI,IAAI,MAAM;AAC3C,IAAI,UAAU,gBACZ,qBAAqB,IACnB,SAAS,eACR,qBAAqB,IAAI,SAAS,YAAY,KAAK,KAAK,CAAC,GAG9D,kBAAkB,IAAI,IAAI,SAAS;EACrC;AAEA,QAAM,oBAAoB,eAAe,QACnC,8BAA8B,eAAe,QAG7C,oBAAoB,MAAM,KAAK,WAAW,EAAE,OAChD,CAAC,QAAQ,qBAAqB,IAAI,EAAE,KAAK,OAAO,CAAC,GAE7C,sBAAsB,iBAC1B,gBAAgB,IAAK,kBAAkB,SAAS,gBAAiB,MAAM,CAAC,GAIpE,sBAAsB,QACzB,iBAAiB,OAAO,EACxB,IAAI,CAAC,MAAM,EAAE,SAAS,GACnB,wBAAwB,IAAI,IAAI,mBAAmB,GAGnD,iBAAiB,MAAM,KAAK,iBAAiB,EAAE,OAAO,CAAC,MAC3D,sBAAsB,IAAI,CAAC,CAAC,GAGxB,wBAAwB,iBAC5B,oBAAoB,SAAS,IACxB,eAAe,SAAS,oBAAoB,SAAU,MACvD,CAAC,GAGD,2BACJ,gBAAgB,IAAI,oBAAoB,gBAAgB;AAE1D,SAAO;IACL,OAAO;IACP;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,68 @@
1
+ import { duplicateImpactScore } from "../../types.js";
2
+ import { isValidRelationship } from "../../../generated/relationship-index.js";
3
+ function detectModelDuplicates(relationships, elements, catalog) {
4
+ const candidates = [], elementById = /* @__PURE__ */ new Map();
5
+ for (const e of elements)
6
+ elementById.set(e.id, e), e.path && e.path !== e.id && elementById.set(e.path, e);
7
+ const exactGroups = /* @__PURE__ */ new Map();
8
+ for (const rel of relationships) {
9
+ const key = `${rel.source}|${rel.predicate}|${rel.target}`, group = exactGroups.get(key) ?? [];
10
+ group.push(rel), exactGroups.set(key, group);
11
+ }
12
+ for (const [compositeKey, group] of exactGroups) {
13
+ if (group.length < 2)
14
+ continue;
15
+ const rel = group[0], srcEl = elementById.get(rel.source), dstEl = elementById.get(rel.target), exactImpactScore = duplicateImpactScore("high");
16
+ candidates.push({
17
+ relationships: [compositeKey, compositeKey],
18
+ predicates: [rel.predicate, rel.predicate],
19
+ sourceNodeType: srcEl?.spec_node_id ?? rel.source,
20
+ destinationNodeType: dstEl?.spec_node_id ?? rel.target,
21
+ reason: `Exact duplicate: (${rel.source}, ${rel.predicate}, ${rel.target}) appears ${group.length} times`,
22
+ confidence: "high",
23
+ impactScore: exactImpactScore,
24
+ alignmentScore: 100 - exactImpactScore
25
+ });
26
+ }
27
+ const semanticGroups = /* @__PURE__ */ new Map();
28
+ for (const rel of relationships) {
29
+ const srcEl = elementById.get(rel.source), dstEl = elementById.get(rel.target);
30
+ if (!srcEl?.spec_node_id || !dstEl?.spec_node_id)
31
+ continue;
32
+ const key = `${rel.source}|${rel.target}`, group = semanticGroups.get(key) ?? [];
33
+ group.push({ predicate: rel.predicate, sourceId: rel.source, targetId: rel.target, sourceSpecNodeId: srcEl.spec_node_id, destSpecNodeId: dstEl.spec_node_id }), semanticGroups.set(key, group);
34
+ }
35
+ for (const [_key, group] of semanticGroups) {
36
+ if (group.length < 2)
37
+ continue;
38
+ const sourceSpecNodeId = group[0].sourceSpecNodeId, destSpecNodeId = group[0].destSpecNodeId;
39
+ for (let i = 0; i < group.length; i++)
40
+ for (let j = i + 1; j < group.length; j++) {
41
+ const p1 = group[i].predicate, p2 = group[j].predicate;
42
+ if (p1 === p2)
43
+ continue;
44
+ const type1 = catalog.getTypeByPredicate(p1), type2 = catalog.getTypeByPredicate(p2);
45
+ if (!type1 || !type2 || type1.category !== type2.category || isValidRelationship(sourceSpecNodeId, p1, destSpecNodeId) && isValidRelationship(sourceSpecNodeId, p2, destSpecNodeId))
46
+ continue;
47
+ const confidence = assessSemanticConfidence(type1, type2), semImpactScore = duplicateImpactScore(confidence), rel1Key = `${group[i].sourceId}|${p1}|${group[i].targetId}`, rel2Key = `${group[j].sourceId}|${p2}|${group[j].targetId}`;
48
+ candidates.push({
49
+ relationships: [rel1Key, rel2Key],
50
+ predicates: [p1, p2],
51
+ sourceNodeType: sourceSpecNodeId ?? "",
52
+ destinationNodeType: destSpecNodeId ?? "",
53
+ reason: `Both predicates '${p1}' and '${p2}' are in "${type1.category}" category between the same element pair`,
54
+ confidence,
55
+ impactScore: semImpactScore,
56
+ alignmentScore: 100 - semImpactScore
57
+ });
58
+ }
59
+ }
60
+ return candidates;
61
+ }
62
+ function assessSemanticConfidence(type1, type2) {
63
+ return !type1 || !type2 ? "low" : type1.category === type2.category && type1.semantics.transitivity === type2.semantics.transitivity && type1.semantics.symmetry === type2.semantics.symmetry ? "high" : type1.category === type2.category ? "medium" : "low";
64
+ }
65
+ export {
66
+ detectModelDuplicates
67
+ };
68
+ //# sourceMappingURL=duplicate-detector.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/model/duplicate-detector.ts"],
4
+ "sourcesContent": ["/**\n * Model Duplicate Detector - Identifies duplicate relationship instances in the model\n *\n * Detects:\n * - Exact duplicates: same (source, predicate, target) triple appearing more than once\n * - Semantic duplicates: same (source_id, target_id) instance pair connected by multiple\n * predicates in the same semantic category\n */\n\nimport { RelationshipCatalog } from \"../../../core/relationship-catalog.js\";\nimport type { Relationship } from \"../../../core/relationships.js\";\nimport type { Element } from \"../../../core/element.js\";\nimport { duplicateImpactScore, type DuplicateCandidate } from \"../../types.js\";\nimport { isValidRelationship } from \"../../../generated/relationship-index.js\";\n\n/**\n * Detect duplicates within a set of model relationship instances\n */\nexport function detectModelDuplicates(\n relationships: Relationship[],\n elements: Element[],\n catalog: RelationshipCatalog\n): DuplicateCandidate[] {\n const candidates: DuplicateCandidate[] = [];\n // Index by both UUID id and path/slug \u2014 relationships store slug paths.\n const elementById = new Map<string, Element>();\n for (const e of elements) {\n elementById.set(e.id, e);\n if (e.path && e.path !== e.id) elementById.set(e.path, e);\n }\n\n // --- Exact duplicates: same (source, predicate, target) ---\n const exactGroups = new Map<string, Relationship[]>();\n for (const rel of relationships) {\n const key = `${rel.source}|${rel.predicate}|${rel.target}`;\n const group = exactGroups.get(key) ?? [];\n group.push(rel);\n exactGroups.set(key, group);\n }\n\n for (const [compositeKey, group] of exactGroups) {\n if (group.length < 2) continue;\n const rel = group[0];\n const srcEl = elementById.get(rel.source);\n const dstEl = elementById.get(rel.target);\n // Use the composite key as both tuple elements so the differential-analyzer\n // produces a stable, unique signature for this duplicate pair.\n const exactImpactScore = duplicateImpactScore(\"high\");\n candidates.push({\n relationships: [compositeKey, compositeKey],\n predicates: [rel.predicate, rel.predicate],\n sourceNodeType: srcEl?.spec_node_id ?? rel.source,\n destinationNodeType: dstEl?.spec_node_id ?? rel.target,\n reason: `Exact duplicate: (${rel.source}, ${rel.predicate}, ${rel.target}) appears ${group.length} times`,\n confidence: \"high\",\n impactScore: exactImpactScore,\n alignmentScore: 100 - exactImpactScore,\n });\n }\n\n // --- Semantic duplicates: same (source_id, target_id) instance pair with same predicate category ---\n // Group by actual element instance pair so we only flag cases where the same two specific\n // elements are connected by multiple predicates in the same semantic category. Grouping by\n // node type instead would flag every pair of elements sharing the same types as duplicates,\n // producing a false-positive explosion in any well-related model.\n const semanticGroups = new Map<\n string,\n Array<{ predicate: string; sourceId: string; targetId: string; sourceSpecNodeId: string; destSpecNodeId: string }>\n >();\n\n for (const rel of relationships) {\n const srcEl = elementById.get(rel.source);\n const dstEl = elementById.get(rel.target);\n if (!srcEl?.spec_node_id || !dstEl?.spec_node_id) continue;\n const key = `${rel.source}|${rel.target}`;\n const group = semanticGroups.get(key) ?? [];\n group.push({ predicate: rel.predicate, sourceId: rel.source, targetId: rel.target, sourceSpecNodeId: srcEl.spec_node_id, destSpecNodeId: dstEl.spec_node_id });\n semanticGroups.set(key, group);\n }\n\n for (const [_key, group] of semanticGroups) {\n if (group.length < 2) continue;\n // All entries share the same source/target instance; take type info from the first entry.\n const sourceSpecNodeId = group[0].sourceSpecNodeId;\n const destSpecNodeId = group[0].destSpecNodeId;\n\n // Check all pairs for same-category predicates\n for (let i = 0; i < group.length; i++) {\n for (let j = i + 1; j < group.length; j++) {\n const p1 = group[i].predicate;\n const p2 = group[j].predicate;\n if (p1 === p2) continue; // Already caught as exact duplicate above\n\n const type1 = catalog.getTypeByPredicate(p1);\n const type2 = catalog.getTypeByPredicate(p2);\n if (!type1 || !type2) continue;\n if (type1.category !== type2.category) continue;\n\n // If both predicates are explicitly spec-valid for this exact source\u2192target node type\n // pair, the combination is intentional \u2014 not a duplicate. Skip it.\n if (\n isValidRelationship(sourceSpecNodeId, p1, destSpecNodeId) &&\n isValidRelationship(sourceSpecNodeId, p2, destSpecNodeId)\n ) {\n continue;\n }\n\n const confidence = assessSemanticConfidence(type1, type2);\n const semImpactScore = duplicateImpactScore(confidence);\n // Use composite keys of each relationship instance so the differential-analyzer\n // can build a stable, unique signature for each semantic duplicate pair.\n const rel1Key = `${group[i].sourceId}|${p1}|${group[i].targetId}`;\n const rel2Key = `${group[j].sourceId}|${p2}|${group[j].targetId}`;\n candidates.push({\n relationships: [rel1Key, rel2Key],\n predicates: [p1, p2],\n sourceNodeType: sourceSpecNodeId ?? \"\",\n destinationNodeType: destSpecNodeId ?? \"\",\n reason: `Both predicates '${p1}' and '${p2}' are in \"${type1.category}\" category between the same element pair`,\n confidence,\n impactScore: semImpactScore,\n alignmentScore: 100 - semImpactScore,\n });\n }\n }\n }\n\n return candidates;\n}\n\nfunction assessSemanticConfidence(\n type1: ReturnType<RelationshipCatalog[\"getTypeByPredicate\"]>,\n type2: ReturnType<RelationshipCatalog[\"getTypeByPredicate\"]>\n): \"high\" | \"medium\" | \"low\" {\n if (!type1 || !type2) return \"low\";\n if (\n type1.category === type2.category &&\n type1.semantics.transitivity === type2.semantics.transitivity &&\n type1.semantics.symmetry === type2.semantics.symmetry\n ) {\n return \"high\";\n }\n if (type1.category === type2.category) {\n return \"medium\";\n }\n return \"low\";\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,41 @@
1
+ import { RELATIONSHIPS_BY_SOURCE } from "../../../generated/relationship-index.js";
2
+ import { gapImpactScore } from "../../types.js";
3
+ function analyzeLayerGaps(elements, intraLayerRels) {
4
+ const candidates = [], presentSpecNodeIds = new Set(elements.map((e) => e.spec_node_id).filter(Boolean)), elementById = /* @__PURE__ */ new Map();
5
+ for (const e of elements)
6
+ elementById.set(e.id, e), e.path && e.path !== e.id && elementById.set(e.path, e);
7
+ const usedCombinations = /* @__PURE__ */ new Set();
8
+ for (const rel of intraLayerRels) {
9
+ const srcEl = elementById.get(rel.source), dstEl = elementById.get(rel.target);
10
+ srcEl?.spec_node_id && dstEl?.spec_node_id && usedCombinations.add(`${srcEl.spec_node_id}|${rel.predicate}|${dstEl.spec_node_id}`);
11
+ }
12
+ for (const sourceSpecNodeId of presentSpecNodeIds) {
13
+ const specRels = RELATIONSHIPS_BY_SOURCE.get(sourceSpecNodeId) ?? [];
14
+ for (const specRel of specRels) {
15
+ const { destinationSpecNodeId, predicate, strength } = specRel, srcLayer = sourceSpecNodeId.split(".")[0], dstLayer = destinationSpecNodeId.split(".")[0];
16
+ if (srcLayer !== dstLayer || !presentSpecNodeIds.has(destinationSpecNodeId))
17
+ continue;
18
+ const key = `${sourceSpecNodeId}|${predicate}|${destinationSpecNodeId}`;
19
+ if (usedCombinations.has(key))
20
+ continue;
21
+ const priority = mapStrengthToPriority(strength), impactScore = gapImpactScore(priority);
22
+ candidates.push({
23
+ sourceNodeType: sourceSpecNodeId,
24
+ destinationNodeType: destinationSpecNodeId,
25
+ suggestedPredicate: predicate,
26
+ reason: `No '${predicate}' relationship instances found between ${sourceSpecNodeId} and ${destinationSpecNodeId} in the model`,
27
+ priority,
28
+ impactScore,
29
+ alignmentScore: 100 - impactScore
30
+ });
31
+ }
32
+ }
33
+ return candidates;
34
+ }
35
+ function mapStrengthToPriority(strength) {
36
+ return strength === "critical" || strength === "high" ? "high" : strength === "medium" ? "medium" : "low";
37
+ }
38
+ export {
39
+ analyzeLayerGaps
40
+ };
41
+ //# sourceMappingURL=gap-analyzer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/model/gap-analyzer.ts"],
4
+ "sourcesContent": ["/**\n * Model Gap Analyzer - Identifies missing relationship instances in the model\n *\n * For each spec-defined relationship type (source_spec_node_id \u2192 predicate \u2192 dest_spec_node_id):\n * - If both endpoint spec_node_ids have at least one element instance in the model\n * - And zero instances of that (source_type, predicate, dest_type) combination exist\n * - \u2192 Report as a gap\n */\n\nimport { RELATIONSHIPS_BY_SOURCE } from \"../../../generated/relationship-index.js\";\nimport type { Relationship } from \"../../../core/relationships.js\";\nimport type { Element } from \"../../../core/element.js\";\nimport { gapImpactScore, type GapCandidate } from \"../../types.js\";\n\n/**\n * Analyze gaps for a single layer\n */\nexport function analyzeLayerGaps(\n elements: Element[],\n intraLayerRels: Relationship[]\n): GapCandidate[] {\n const candidates: GapCandidate[] = [];\n\n // Build set of spec_node_ids that have at least one element instance\n const presentSpecNodeIds = new Set<string>(\n elements.map((e) => e.spec_node_id).filter(Boolean)\n );\n\n // Build set of (source_spec_node_id, predicate, dest_spec_node_id) tuples already in use.\n // Index by both UUID id and path/slug \u2014 relationships store slug paths.\n const elementById = new Map<string, Element>();\n for (const e of elements) {\n elementById.set(e.id, e);\n if (e.path && e.path !== e.id) elementById.set(e.path, e);\n }\n\n const usedCombinations = new Set<string>();\n for (const rel of intraLayerRels) {\n const srcEl = elementById.get(rel.source);\n const dstEl = elementById.get(rel.target);\n if (srcEl?.spec_node_id && dstEl?.spec_node_id) {\n usedCombinations.add(\n `${srcEl.spec_node_id}|${rel.predicate}|${dstEl.spec_node_id}`\n );\n }\n }\n\n // Check each spec-defined relationship for the node types present in this layer\n for (const sourceSpecNodeId of presentSpecNodeIds) {\n const specRels = RELATIONSHIPS_BY_SOURCE.get(sourceSpecNodeId) ?? [];\n for (const specRel of specRels) {\n const { destinationSpecNodeId, predicate, strength } = specRel;\n\n // Only consider intra-layer gaps (same layer prefix)\n const srcLayer = sourceSpecNodeId.split(\".\")[0];\n const dstLayer = destinationSpecNodeId.split(\".\")[0];\n if (srcLayer !== dstLayer) {\n continue;\n }\n\n // Both sides must have instances in the model\n if (!presentSpecNodeIds.has(destinationSpecNodeId)) {\n continue;\n }\n\n // Skip if at least one instance of this combination already exists\n const key = `${sourceSpecNodeId}|${predicate}|${destinationSpecNodeId}`;\n if (usedCombinations.has(key)) {\n continue;\n }\n\n const priority = mapStrengthToPriority(strength);\n const impactScore = gapImpactScore(priority);\n candidates.push({\n sourceNodeType: sourceSpecNodeId,\n destinationNodeType: destinationSpecNodeId,\n suggestedPredicate: predicate,\n reason: `No '${predicate}' relationship instances found between ${sourceSpecNodeId} and ${destinationSpecNodeId} in the model`,\n priority,\n impactScore,\n alignmentScore: 100 - impactScore,\n });\n }\n }\n\n return candidates;\n}\n\nfunction mapStrengthToPriority(\n strength: \"critical\" | \"high\" | \"medium\" | \"low\"\n): \"high\" | \"medium\" | \"low\" {\n if (strength === \"critical\" || strength === \"high\") {\n return \"high\";\n }\n if (strength === \"medium\") {\n return \"medium\";\n }\n return \"low\";\n}\n"],
5
+ "mappings": "AASA,SAAS,+BAA+B;AAGxC,SAAS,sBAAyC;AAK5C,SAAU,iBACd,UACA,gBAA8B;AAE9B,QAAM,aAA6B,CAAA,GAG7B,qBAAqB,IAAI,IAC7B,SAAS,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,OAAO,CAAC,GAK/C,cAAc,oBAAI,IAAG;AAC3B,aAAW,KAAK;AACd,gBAAY,IAAI,EAAE,IAAI,CAAC,GACnB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAI,YAAY,IAAI,EAAE,MAAM,CAAC;AAG1D,QAAM,mBAAmB,oBAAI,IAAG;AAChC,aAAW,OAAO,gBAAgB;AAChC,UAAM,QAAQ,YAAY,IAAI,IAAI,MAAM,GAClC,QAAQ,YAAY,IAAI,IAAI,MAAM;AACxC,IAAI,OAAO,gBAAgB,OAAO,gBAChC,iBAAiB,IACf,GAAG,MAAM,YAAY,IAAI,IAAI,SAAS,IAAI,MAAM,YAAY,EAAE;EAGpE;AAGA,aAAW,oBAAoB,oBAAoB;AACjD,UAAM,WAAW,wBAAwB,IAAI,gBAAgB,KAAK,CAAA;AAClE,eAAW,WAAW,UAAU;AAC9B,YAAM,EAAE,uBAAuB,WAAW,SAAQ,IAAK,SAGjD,WAAW,iBAAiB,MAAM,GAAG,EAAE,CAAC,GACxC,WAAW,sBAAsB,MAAM,GAAG,EAAE,CAAC;AAMnD,UALI,aAAa,YAKb,CAAC,mBAAmB,IAAI,qBAAqB;AAC/C;AAIF,YAAM,MAAM,GAAG,gBAAgB,IAAI,SAAS,IAAI,qBAAqB;AACrE,UAAI,iBAAiB,IAAI,GAAG;AAC1B;AAGF,YAAM,WAAW,sBAAsB,QAAQ,GACzC,cAAc,eAAe,QAAQ;AAC3C,iBAAW,KAAK;QACd,gBAAgB;QAChB,qBAAqB;QACrB,oBAAoB;QACpB,QAAQ,OAAO,SAAS,0CAA0C,gBAAgB,QAAQ,qBAAqB;QAC/G;QACA;QACA,gBAAgB,MAAM;OACvB;IACH;EACF;AAEA,SAAO;AACT;AAEA,SAAS,sBACP,UAAgD;AAEhD,SAAI,aAAa,cAAc,aAAa,SACnC,SAEL,aAAa,WACR,WAEF;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,126 @@
1
+ import { Model } from "../../../core/model.js";
2
+ import { RelationshipCatalog } from "../../../core/relationship-catalog.js";
3
+ import { RelationshipGraph } from "../graph/relationship-graph.js";
4
+ import { ConnectivityAnalyzer } from "../graph/connectivity.js";
5
+ import { analyzeLayerCoverage } from "./coverage-analyzer.js";
6
+ import { analyzeLayerGaps } from "./gap-analyzer.js";
7
+ import { detectModelDuplicates } from "./duplicate-detector.js";
8
+ import { assessLayerBalance } from "./balance-assessor.js";
9
+ import { getAllLayers, getLayerById } from "../../../generated/layer-registry.js";
10
+ class ModelAuditOrchestrator {
11
+ catalog;
12
+ graph;
13
+ initialized = !1;
14
+ constructor() {
15
+ this.catalog = new RelationshipCatalog(), this.graph = new RelationshipGraph();
16
+ }
17
+ async initialize() {
18
+ this.initialized || (await this.catalog.load(), this.initialized = !0);
19
+ }
20
+ /**
21
+ * Get predicates applicable to a specific layer (same API as AuditOrchestrator)
22
+ */
23
+ getPredicatesForLayer(layer) {
24
+ return this.catalog.getTypesForLayer(layer).map((t) => t.predicate);
25
+ }
26
+ /**
27
+ * Run complete audit against the project model
28
+ */
29
+ async runAudit(options = {}) {
30
+ await this.initialize();
31
+ const projectRoot = options.projectRoot ?? process.cwd();
32
+ let model;
33
+ try {
34
+ model = await Model.load(projectRoot);
35
+ } catch (err) {
36
+ throw new Error(`Failed to load project model from ${projectRoot}: ${err instanceof Error ? err.message : String(err)}`);
37
+ }
38
+ const allElements = [];
39
+ for (const layer of model.layers.values())
40
+ for (const el of layer.elements.values())
41
+ allElements.push(el);
42
+ const elementById = /* @__PURE__ */ new Map();
43
+ for (const e of allElements)
44
+ elementById.set(e.id, e), e.path && e.path !== e.id && elementById.set(e.path, e);
45
+ const allRelationships = model.relationships.getAll(), getElementLayer = (el) => el.layer_id || el.layer || "", elementsByLayer = /* @__PURE__ */ new Map();
46
+ for (const el of allElements) {
47
+ const layerId = getElementLayer(el);
48
+ if (!layerId)
49
+ continue;
50
+ const list = elementsByLayer.get(layerId) ?? [];
51
+ list.push(el), elementsByLayer.set(layerId, list);
52
+ }
53
+ const intraRelsByLayer = /* @__PURE__ */ new Map(), interRelsByLayer = /* @__PURE__ */ new Map(), incomingInterRelsByLayer = /* @__PURE__ */ new Map();
54
+ for (const rel of allRelationships) {
55
+ const srcEl = elementById.get(rel.source), dstEl = elementById.get(rel.target);
56
+ if (!srcEl || !dstEl)
57
+ continue;
58
+ const srcLayer = getElementLayer(srcEl), dstLayer = getElementLayer(dstEl);
59
+ if (srcLayer)
60
+ if (srcLayer === dstLayer) {
61
+ const list = intraRelsByLayer.get(srcLayer) ?? [];
62
+ list.push(rel), intraRelsByLayer.set(srcLayer, list);
63
+ } else {
64
+ const outList = interRelsByLayer.get(srcLayer) ?? [];
65
+ if (outList.push(rel), interRelsByLayer.set(srcLayer, outList), dstLayer) {
66
+ const inList = incomingInterRelsByLayer.get(dstLayer) ?? [];
67
+ inList.push(rel), incomingInterRelsByLayer.set(dstLayer, inList);
68
+ }
69
+ }
70
+ }
71
+ const layersToAnalyze = this.resolveTargetLayers(options.layer), coverage = [], gaps = [], balance = [];
72
+ for (const layerMeta of layersToAnalyze) {
73
+ const layerId = layerMeta.id, layerElements = elementsByLayer.get(layerId) ?? [], layerRels = intraRelsByLayer.get(layerId) ?? [], layerInterRels2 = [
74
+ ...interRelsByLayer.get(layerId) ?? [],
75
+ ...incomingInterRelsByLayer.get(layerId) ?? []
76
+ ];
77
+ coverage.push(analyzeLayerCoverage(layerId, layerElements, layerRels, layerInterRels2, this.catalog)), gaps.push(...analyzeLayerGaps(layerElements, layerRels)), balance.push(...assessLayerBalance(layerId, layerElements, layerRels));
78
+ }
79
+ const relsForDuplicates = options.layer ? intraRelsByLayer.get(options.layer) ?? [] : allRelationships, elementsForDuplicates = options.layer ? elementsByLayer.get(options.layer) ?? [] : allElements, duplicates = detectModelDuplicates(relsForDuplicates, elementsForDuplicates, this.catalog), layerOutgoingInterRels = options.layer ? interRelsByLayer.get(options.layer) ?? [] : [], layerIncomingInterRels = options.layer ? incomingInterRelsByLayer.get(options.layer) ?? [] : [], layerInterRels = [...layerOutgoingInterRels, ...layerIncomingInterRels], relsForGraph = options.layer ? [...intraRelsByLayer.get(options.layer) ?? [], ...layerInterRels] : allRelationships, crossLayerTargetIds = new Set(layerOutgoingInterRels.map((r) => r.target)), crossLayerSourceIds = new Set(layerIncomingInterRels.map((r) => r.source)), crossLayerAdjacentElements = allElements.filter((e) => crossLayerTargetIds.has(e.id) || e.path != null && crossLayerTargetIds.has(e.path) || crossLayerSourceIds.has(e.id) || e.path != null && crossLayerSourceIds.has(e.path)), elementsForGraph = options.layer ? [...elementsByLayer.get(options.layer) ?? [], ...crossLayerAdjacentElements] : allElements;
80
+ this.graph.buildFromModel(relsForGraph, elementsForGraph);
81
+ const connectivityAnalyzer = new ConnectivityAnalyzer(this.graph, this.catalog), components = connectivityAnalyzer.findConnectedComponents(), degrees = connectivityAnalyzer.calculateDegreeDistribution(), transitiveChains = await connectivityAnalyzer.findTransitiveChains(), rawStats = connectivityAnalyzer.getConnectivityStats(), connectivityStats = {
82
+ totalNodes: rawStats.nodeCount,
83
+ totalEdges: rawStats.edgeCount,
84
+ connectedComponents: rawStats.componentCount,
85
+ largestComponentSize: rawStats.largestComponentSize,
86
+ isolatedNodes: rawStats.isolatedNodeCount,
87
+ averageDegree: rawStats.averageDegree,
88
+ transitiveChainCount: transitiveChains.length
89
+ }, modelMetadata = {
90
+ name: model.manifest.name ?? "Documentation Robotics Model",
91
+ version: model.manifest.version ?? "1.0.0"
92
+ };
93
+ return this.log(options, "Generating model audit report..."), {
94
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
95
+ model: modelMetadata,
96
+ coverage,
97
+ duplicates,
98
+ gaps,
99
+ balance,
100
+ connectivity: {
101
+ components,
102
+ degrees,
103
+ transitiveChains,
104
+ stats: connectivityStats
105
+ }
106
+ };
107
+ }
108
+ resolveTargetLayers(layerFilter) {
109
+ if (layerFilter) {
110
+ const layer = getLayerById(layerFilter);
111
+ if (!layer) {
112
+ const valid = getAllLayers().map((l) => l.id).join(", ");
113
+ throw new Error(`Layer not found: '${layerFilter}'. Valid layers: ${valid}`);
114
+ }
115
+ return [layer];
116
+ }
117
+ return getAllLayers();
118
+ }
119
+ log(options, message) {
120
+ (options.verbose || options.debug) && console.error(message);
121
+ }
122
+ }
123
+ export {
124
+ ModelAuditOrchestrator
125
+ };
126
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/relationships/model/orchestrator.ts"],
4
+ "sourcesContent": ["/**\n * Model Audit Orchestrator - Runs audit analysis against the project's actual model\n *\n * Loads the project model via Model.fromDirectory() and runs the four model-specific\n * analyzers (coverage, gaps, duplicates, balance) plus connectivity, producing an\n * AuditReport in the same format as AuditOrchestrator.\n */\n\nimport { Model } from \"../../../core/model.js\";\nimport { RelationshipCatalog } from \"../../../core/relationship-catalog.js\";\nimport { RelationshipGraph } from \"../graph/relationship-graph.js\";\nimport { ConnectivityAnalyzer } from \"../graph/connectivity.js\";\nimport { analyzeLayerCoverage } from \"./coverage-analyzer.js\";\nimport { analyzeLayerGaps } from \"./gap-analyzer.js\";\nimport { detectModelDuplicates } from \"./duplicate-detector.js\";\nimport { assessLayerBalance } from \"./balance-assessor.js\";\nimport { getAllLayers, getLayerById } from \"../../../generated/layer-registry.js\";\nimport type { Element } from \"../../../core/element.js\";\nimport type { Relationship } from \"../../../core/relationships.js\";\nimport type {\n AuditReport,\n ConnectivityStats,\n CoverageMetrics,\n DuplicateCandidate,\n GapCandidate,\n BalanceAssessment,\n} from \"../../types.js\";\n\nexport interface ModelAuditOptions {\n layer?: string;\n verbose?: boolean;\n debug?: boolean;\n projectRoot?: string;\n}\n\n/**\n * Orchestrates audit of the project's model relationship instances\n */\nexport class ModelAuditOrchestrator {\n private catalog: RelationshipCatalog;\n private graph: RelationshipGraph;\n private initialized = false;\n\n constructor() {\n this.catalog = new RelationshipCatalog();\n this.graph = new RelationshipGraph();\n }\n\n async initialize(): Promise<void> {\n if (!this.initialized) {\n await this.catalog.load();\n this.initialized = true;\n }\n }\n\n /**\n * Get predicates applicable to a specific layer (same API as AuditOrchestrator)\n */\n getPredicatesForLayer(layer: string): string[] {\n return this.catalog.getTypesForLayer(layer).map((t) => t.predicate);\n }\n\n /**\n * Run complete audit against the project model\n */\n async runAudit(options: ModelAuditOptions = {}): Promise<AuditReport> {\n await this.initialize();\n\n const projectRoot = options.projectRoot ?? process.cwd();\n\n // Load model (layers + relationships)\n let model: Model;\n try {\n model = await Model.load(projectRoot);\n } catch (err) {\n throw new Error(\n `Failed to load project model from ${projectRoot}: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n // Collect all elements across all layers\n const allElements: Element[] = [];\n for (const layer of model.layers.values()) {\n for (const el of layer.elements.values()) {\n allElements.push(el);\n }\n }\n\n // Build element lookup by both UUID id and path/slug (for resolving relationship\n // endpoints, which are stored as slug paths in relationships.yaml).\n const elementById = new Map<string, Element>();\n for (const e of allElements) {\n elementById.set(e.id, e);\n if (e.path && e.path !== e.id) elementById.set(e.path, e);\n }\n\n // All relationship instances from relationships.yaml\n const allRelationships: Relationship[] = model.relationships.getAll();\n\n // Resolve canonical layer for each element\n // Elements may have layer_id (spec-aligned) or layer (legacy) set\n const getElementLayer = (el: Element): string =>\n el.layer_id || el.layer || \"\";\n\n // Build per-layer element and intra-layer relationship maps\n const elementsByLayer = new Map<string, Element[]>();\n for (const el of allElements) {\n const layerId = getElementLayer(el);\n if (!layerId) continue;\n const list = elementsByLayer.get(layerId) ?? [];\n list.push(el);\n elementsByLayer.set(layerId, list);\n }\n\n // Intra-layer rels: both source and target element are in the same layer\n const intraRelsByLayer = new Map<string, Relationship[]>();\n // Inter-layer rels keyed by source layer (outgoing)\n const interRelsByLayer = new Map<string, Relationship[]>();\n // Inter-layer rels keyed by destination layer (incoming)\n const incomingInterRelsByLayer = new Map<string, Relationship[]>();\n for (const rel of allRelationships) {\n const srcEl = elementById.get(rel.source);\n const dstEl = elementById.get(rel.target);\n if (!srcEl || !dstEl) continue;\n const srcLayer = getElementLayer(srcEl);\n const dstLayer = getElementLayer(dstEl);\n if (!srcLayer) continue;\n if (srcLayer === dstLayer) {\n const list = intraRelsByLayer.get(srcLayer) ?? [];\n list.push(rel);\n intraRelsByLayer.set(srcLayer, list);\n } else {\n const outList = interRelsByLayer.get(srcLayer) ?? [];\n outList.push(rel);\n interRelsByLayer.set(srcLayer, outList);\n if (dstLayer) {\n const inList = incomingInterRelsByLayer.get(dstLayer) ?? [];\n inList.push(rel);\n incomingInterRelsByLayer.set(dstLayer, inList);\n }\n }\n }\n\n // Determine which layers to analyze\n const layersToAnalyze = this.resolveTargetLayers(options.layer);\n\n // --- Run per-layer analysis ---\n const coverage: CoverageMetrics[] = [];\n const gaps: GapCandidate[] = [];\n const balance: BalanceAssessment[] = [];\n\n for (const layerMeta of layersToAnalyze) {\n const layerId = layerMeta.id;\n const layerElements = elementsByLayer.get(layerId) ?? [];\n const layerRels = intraRelsByLayer.get(layerId) ?? [];\n // Include both outgoing (source=this layer) and incoming (target=this layer) inter-layer rels\n const layerInterRels = [\n ...(interRelsByLayer.get(layerId) ?? []),\n ...(incomingInterRelsByLayer.get(layerId) ?? []),\n ];\n\n coverage.push(\n analyzeLayerCoverage(layerId, layerElements, layerRels, layerInterRels, this.catalog)\n );\n gaps.push(...analyzeLayerGaps(layerElements, layerRels));\n balance.push(...assessLayerBalance(layerId, layerElements, layerRels));\n }\n\n // --- Duplicates (cross-layer or per-layer, depending on filter) ---\n const relsForDuplicates = options.layer\n ? (intraRelsByLayer.get(options.layer) ?? [])\n : allRelationships;\n const elementsForDuplicates = options.layer\n ? (elementsByLayer.get(options.layer) ?? [])\n : allElements;\n\n const duplicates: DuplicateCandidate[] = detectModelDuplicates(\n relsForDuplicates,\n elementsForDuplicates,\n this.catalog\n );\n\n // --- Connectivity ---\n // For per-layer audits, include both outgoing and incoming inter-layer rels so that\n // node types are not incorrectly classified as isolated when they only have cross-layer\n // connections (in either direction). Also include adjacent elements from both sides so\n // buildFromModel can resolve all relationship endpoints.\n const layerOutgoingInterRels = options.layer ? (interRelsByLayer.get(options.layer) ?? []) : [];\n const layerIncomingInterRels = options.layer ? (incomingInterRelsByLayer.get(options.layer) ?? []) : [];\n const layerInterRels = [...layerOutgoingInterRels, ...layerIncomingInterRels];\n const relsForGraph = options.layer\n ? [...(intraRelsByLayer.get(options.layer) ?? []), ...layerInterRels]\n : allRelationships;\n const crossLayerTargetIds = new Set<string>(layerOutgoingInterRels.map((r) => r.target));\n const crossLayerSourceIds = new Set<string>(layerIncomingInterRels.map((r) => r.source));\n const crossLayerAdjacentElements = allElements.filter(\n (e) =>\n crossLayerTargetIds.has(e.id) ||\n (e.path != null && crossLayerTargetIds.has(e.path)) ||\n crossLayerSourceIds.has(e.id) ||\n (e.path != null && crossLayerSourceIds.has(e.path))\n );\n const elementsForGraph = options.layer\n ? [...(elementsByLayer.get(options.layer) ?? []), ...crossLayerAdjacentElements]\n : allElements;\n\n this.graph.buildFromModel(relsForGraph, elementsForGraph);\n\n // Create a fresh ConnectivityAnalyzer each run so its internal caches\n // (cachedComponents, cachedDegrees) always reflect the current graph state.\n const connectivityAnalyzer = new ConnectivityAnalyzer(this.graph, this.catalog);\n const components = connectivityAnalyzer.findConnectedComponents();\n const degrees = connectivityAnalyzer.calculateDegreeDistribution();\n const transitiveChains = await connectivityAnalyzer.findTransitiveChains();\n const rawStats = connectivityAnalyzer.getConnectivityStats();\n\n const connectivityStats: ConnectivityStats = {\n totalNodes: rawStats.nodeCount,\n totalEdges: rawStats.edgeCount,\n connectedComponents: rawStats.componentCount,\n largestComponentSize: rawStats.largestComponentSize,\n isolatedNodes: rawStats.isolatedNodeCount,\n averageDegree: rawStats.averageDegree,\n transitiveChainCount: transitiveChains.length,\n };\n\n // Model metadata\n const modelMetadata = {\n name: model.manifest.name ?? \"Documentation Robotics Model\",\n version: model.manifest.version ?? \"1.0.0\",\n };\n\n this.log(options, \"Generating model audit report...\");\n\n return {\n timestamp: new Date().toISOString(),\n model: modelMetadata,\n coverage,\n duplicates,\n gaps,\n balance,\n connectivity: {\n components,\n degrees,\n transitiveChains,\n stats: connectivityStats,\n },\n };\n }\n\n private resolveTargetLayers(layerFilter?: string) {\n if (layerFilter) {\n const layer = getLayerById(layerFilter);\n if (!layer) {\n const valid = getAllLayers()\n .map((l) => l.id)\n .join(\", \");\n throw new Error(\n `Layer not found: '${layerFilter}'. Valid layers: ${valid}`\n );\n }\n return [layer];\n }\n return getAllLayers();\n }\n\n private log(options: ModelAuditOptions, message: string): void {\n if (options.verbose || options.debug) {\n console.error(message);\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["layerInterRels"]
7
+ }