@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,183 @@
1
+ class DifferentialAnalyzer {
2
+ /**
3
+ * Compare two audit reports
4
+ */
5
+ analyze(before, after) {
6
+ const { comparison: coverageComparison, skipped: skippedLayers } = this.analyzeCoverage(before.coverage, after.coverage), gapChanges = this.analyzeGaps(before.gaps, after.gaps), duplicateChanges = this.analyzeDuplicates(before.duplicates, after.duplicates), balanceChanges = this.analyzeBalance(before.balance, after.balance), connectivityChanges = this.analyzeConnectivity(before.connectivity, after.connectivity);
7
+ return {
8
+ summary: this.generateSummary(after.timestamp, coverageComparison, gapChanges, duplicateChanges, balanceChanges),
9
+ detailed: {
10
+ coverageByLayer: coverageComparison,
11
+ gapChanges,
12
+ duplicateChanges,
13
+ balanceChanges,
14
+ connectivityChanges,
15
+ skippedLayers
16
+ }
17
+ };
18
+ }
19
+ /**
20
+ * Analyze coverage changes across layers
21
+ */
22
+ analyzeCoverage(before, after) {
23
+ const comparison = /* @__PURE__ */ new Map(), skipped = [], beforeMap = new Map(before.map((c) => [c.layer, c])), afterMap = new Map(after.map((c) => [c.layer, c]));
24
+ for (const beforeCoverage of before)
25
+ afterMap.has(beforeCoverage.layer) || skipped.push({
26
+ layer: beforeCoverage.layer,
27
+ reason: "only-in-before",
28
+ coverage: beforeCoverage
29
+ });
30
+ for (const afterCoverage of after) {
31
+ const beforeCoverage = beforeMap.get(afterCoverage.layer);
32
+ if (!beforeCoverage) {
33
+ skipped.push({
34
+ layer: afterCoverage.layer,
35
+ reason: "only-in-after",
36
+ coverage: afterCoverage
37
+ });
38
+ continue;
39
+ }
40
+ const deltas = {
41
+ isolationChange: afterCoverage.isolationPercentage - beforeCoverage.isolationPercentage,
42
+ densityChange: afterCoverage.relationshipsPerNodeType - beforeCoverage.relationshipsPerNodeType,
43
+ utilizationChange: afterCoverage.utilizationPercentage - beforeCoverage.utilizationPercentage,
44
+ nodeTypeCountChange: afterCoverage.nodeTypeCount - beforeCoverage.nodeTypeCount,
45
+ relationshipCountChange: afterCoverage.relationshipCount - beforeCoverage.relationshipCount
46
+ }, improvements = [], regressions = [];
47
+ deltas.isolationChange < -5 ? improvements.push(`Isolation reduced by ${Math.abs(deltas.isolationChange).toFixed(1)}%`) : deltas.isolationChange > 5 && regressions.push(`Isolation increased by ${deltas.isolationChange.toFixed(1)}%`), deltas.densityChange > 0.5 ? improvements.push(`Density increased by ${deltas.densityChange.toFixed(2)}`) : deltas.densityChange < -0.5 && regressions.push(`Density decreased by ${Math.abs(deltas.densityChange).toFixed(2)}`), deltas.utilizationChange > 5 ? improvements.push(`Predicate utilization increased by ${deltas.utilizationChange.toFixed(1)}%`) : deltas.utilizationChange < -5 && regressions.push(`Predicate utilization decreased by ${Math.abs(deltas.utilizationChange).toFixed(1)}%`), comparison.set(afterCoverage.layer, {
48
+ layer: afterCoverage.layer,
49
+ before: beforeCoverage,
50
+ after: afterCoverage,
51
+ deltas,
52
+ improvements,
53
+ regressions
54
+ });
55
+ }
56
+ return { comparison, skipped };
57
+ }
58
+ /**
59
+ * Analyze gap changes
60
+ */
61
+ analyzeGaps(before, after) {
62
+ const beforeSigs = new Set(before.map((g) => this.gapSignature(g))), afterSigs = new Set(after.map((g) => this.gapSignature(g))), resolved = before.filter((g) => !afterSigs.has(this.gapSignature(g))), newGaps = after.filter((g) => !beforeSigs.has(this.gapSignature(g))), persistent = after.filter((g) => beforeSigs.has(this.gapSignature(g))), resolutionRate = before.length > 0 ? resolved.length / before.length * 100 : 0;
63
+ return {
64
+ before,
65
+ after,
66
+ resolved,
67
+ newGaps,
68
+ persistent,
69
+ resolutionRate
70
+ };
71
+ }
72
+ /**
73
+ * Generate gap signature for comparison
74
+ */
75
+ gapSignature(gap) {
76
+ return `${gap.sourceNodeType}:${gap.destinationNodeType}:${gap.suggestedPredicate}`;
77
+ }
78
+ /**
79
+ * Analyze duplicate changes
80
+ */
81
+ analyzeDuplicates(before, after) {
82
+ const beforeSigs = new Set(before.map((d) => this.duplicateSignature(d))), afterSigs = new Set(after.map((d) => this.duplicateSignature(d))), resolved = before.filter((d) => !afterSigs.has(this.duplicateSignature(d))), newDuplicates = after.filter((d) => !beforeSigs.has(this.duplicateSignature(d))), persistent = after.filter((d) => beforeSigs.has(this.duplicateSignature(d))), eliminationRate = before.length > 0 ? resolved.length / before.length * 100 : 0;
83
+ return {
84
+ before,
85
+ after,
86
+ resolved,
87
+ newDuplicates,
88
+ persistent,
89
+ eliminationRate
90
+ };
91
+ }
92
+ /**
93
+ * Generate duplicate signature for comparison
94
+ */
95
+ duplicateSignature(dup) {
96
+ const sorted = [...dup.relationships].sort();
97
+ return `${sorted[0]}:${sorted[1]}`;
98
+ }
99
+ /**
100
+ * Analyze balance changes
101
+ */
102
+ analyzeBalance(before, after) {
103
+ const beforeMap = new Map(before.map((b) => [b.nodeType, b])), improvements = [], regressions = [], newlyBalanced = [];
104
+ for (const afterAssessment of after) {
105
+ const beforeAssessment = beforeMap.get(afterAssessment.nodeType);
106
+ if (!beforeAssessment)
107
+ continue;
108
+ const beforeDistance = this.distanceFromBalance(beforeAssessment), afterDistance = this.distanceFromBalance(afterAssessment);
109
+ afterDistance < beforeDistance ? improvements.push(afterAssessment) : afterDistance > beforeDistance && regressions.push(afterAssessment), beforeAssessment.status !== "balanced" && afterAssessment.status === "balanced" && newlyBalanced.push(afterAssessment);
110
+ }
111
+ return {
112
+ before,
113
+ after,
114
+ improvements,
115
+ regressions,
116
+ newlyBalanced
117
+ };
118
+ }
119
+ /**
120
+ * Calculate distance from balanced state
121
+ */
122
+ distanceFromBalance(assessment) {
123
+ const [min, max] = assessment.targetRange, target = (min + max) / 2;
124
+ return Math.abs(assessment.currentCount - target);
125
+ }
126
+ /**
127
+ * Analyze connectivity changes
128
+ */
129
+ analyzeConnectivity(before, after) {
130
+ const beforeStats = {
131
+ componentCount: before.components.length,
132
+ isolatedNodes: before.stats.isolatedNodes,
133
+ averageDegree: before.stats.averageDegree
134
+ }, afterStats = {
135
+ componentCount: after.components.length,
136
+ isolatedNodes: after.stats.isolatedNodes,
137
+ averageDegree: after.stats.averageDegree
138
+ };
139
+ return {
140
+ before: beforeStats,
141
+ after: afterStats,
142
+ deltas: {
143
+ componentChange: afterStats.componentCount - beforeStats.componentCount,
144
+ isolationChange: afterStats.isolatedNodes - beforeStats.isolatedNodes,
145
+ degreeChange: afterStats.averageDegree - beforeStats.averageDegree
146
+ }
147
+ };
148
+ }
149
+ /**
150
+ * Generate summary report
151
+ */
152
+ generateSummary(timestamp, coverageComparison, gapChanges, duplicateChanges, balanceChanges) {
153
+ const coverageChanges = Array.from(coverageComparison.values()).map((comp) => ({
154
+ layer: comp.layer,
155
+ before: {
156
+ isolation: comp.before.isolationPercentage,
157
+ density: comp.before.relationshipsPerNodeType
158
+ },
159
+ after: {
160
+ isolation: comp.after.isolationPercentage,
161
+ density: comp.after.relationshipsPerNodeType
162
+ },
163
+ delta: {
164
+ isolation: comp.deltas.isolationChange,
165
+ density: comp.deltas.densityChange
166
+ }
167
+ })), relationshipsAdded = Array.from(coverageComparison.values()).reduce((sum, comp) => sum + comp.deltas.relationshipCountChange, 0), balanceImprovements = balanceChanges.newlyBalanced.map((b) => `${b.nodeType} achieved balanced density (${b.currentCount} relationships)`);
168
+ return {
169
+ timestamp,
170
+ coverageChanges,
171
+ relationshipsAdded: Math.max(0, relationshipsAdded),
172
+ // Only count additions
173
+ gapsResolved: gapChanges.resolved.length,
174
+ remainingGaps: gapChanges.after.length,
175
+ duplicatesResolved: duplicateChanges.resolved.length,
176
+ balanceImprovements
177
+ };
178
+ }
179
+ }
180
+ export {
181
+ DifferentialAnalyzer
182
+ };
183
+ //# sourceMappingURL=differential-analyzer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/audit/differential-analyzer.ts"],
4
+ "sourcesContent": ["/**\n * Differential analysis for before/after audit comparison\n *\n * Analyzes changes between two audit snapshots to identify\n * improvements, regressions, and trends in relationship quality.\n */\n\nimport {\n AuditReport,\n SummaryReport,\n CoverageMetrics,\n GapCandidate,\n DuplicateCandidate,\n BalanceAssessment,\n} from \"./types.js\";\n\n/**\n * Detailed differential analysis result\n */\nexport interface DifferentialAnalysis {\n summary: SummaryReport;\n detailed: {\n coverageByLayer: Map<string, CoverageComparison>;\n gapChanges: GapChanges;\n duplicateChanges: DuplicateChanges;\n balanceChanges: BalanceChanges;\n connectivityChanges: ConnectivityComparison;\n skippedLayers: SkippedLayer[]; // Layers that couldn't be compared\n };\n}\n\n/**\n * Information about a layer that was skipped during comparison\n */\nexport interface SkippedLayer {\n layer: string;\n reason: \"only-in-before\" | \"only-in-after\";\n coverage?: CoverageMetrics; // Coverage metrics if available\n}\n\n/**\n * Coverage comparison for a single layer\n */\nexport interface CoverageComparison {\n layer: string;\n before: CoverageMetrics;\n after: CoverageMetrics;\n deltas: {\n isolationChange: number; // Negative = improvement\n densityChange: number; // Positive = improvement\n utilizationChange: number; // Positive = improvement\n nodeTypeCountChange: number;\n relationshipCountChange: number;\n };\n improvements: string[];\n regressions: string[];\n}\n\n/**\n * Gap analysis changes\n */\nexport interface GapChanges {\n before: GapCandidate[];\n after: GapCandidate[];\n resolved: GapCandidate[]; // Gaps that disappeared\n newGaps: GapCandidate[]; // New gaps introduced\n persistent: GapCandidate[]; // Gaps still present\n /** Percentage of gaps resolved (0-100) */\n resolutionRate: number;\n}\n\n/**\n * Duplicate analysis changes\n */\nexport interface DuplicateChanges {\n before: DuplicateCandidate[];\n after: DuplicateCandidate[];\n resolved: DuplicateCandidate[]; // Duplicates eliminated\n newDuplicates: DuplicateCandidate[]; // New duplicates introduced\n persistent: DuplicateCandidate[]; // Still duplicated\n /** Percentage of duplicates eliminated (0-100) */\n eliminationRate: number;\n}\n\n/**\n * Balance assessment changes\n */\nexport interface BalanceChanges {\n before: BalanceAssessment[];\n after: BalanceAssessment[];\n improvements: BalanceAssessment[]; // Moved toward balanced\n regressions: BalanceAssessment[]; // Moved away from balanced\n newlyBalanced: BalanceAssessment[]; // Achieved balanced status\n}\n\n/**\n * Connectivity comparison\n */\nexport interface ConnectivityComparison {\n before: {\n componentCount: number;\n isolatedNodes: number;\n averageDegree: number;\n };\n after: {\n componentCount: number;\n isolatedNodes: number;\n averageDegree: number;\n };\n deltas: {\n componentChange: number; // Negative = more connected\n isolationChange: number; // Negative = improvement\n degreeChange: number; // Positive = more connected\n };\n}\n\n/**\n * Analyzer for comparing audit snapshots\n */\nexport class DifferentialAnalyzer {\n /**\n * Compare two audit reports\n */\n analyze(before: AuditReport, after: AuditReport): DifferentialAnalysis {\n const { comparison: coverageComparison, skipped: skippedLayers } =\n this.analyzeCoverage(before.coverage as CoverageMetrics[], after.coverage as CoverageMetrics[]);\n const gapChanges = this.analyzeGaps(before.gaps as GapCandidate[], after.gaps as GapCandidate[]);\n const duplicateChanges = this.analyzeDuplicates(\n before.duplicates as DuplicateCandidate[],\n after.duplicates as DuplicateCandidate[],\n );\n const balanceChanges = this.analyzeBalance(before.balance as BalanceAssessment[], after.balance as BalanceAssessment[]);\n const connectivityChanges = this.analyzeConnectivity(\n before.connectivity,\n after.connectivity,\n );\n\n const summary = this.generateSummary(\n after.timestamp,\n coverageComparison,\n gapChanges,\n duplicateChanges,\n balanceChanges,\n );\n\n return {\n summary,\n detailed: {\n coverageByLayer: coverageComparison,\n gapChanges,\n duplicateChanges,\n balanceChanges,\n connectivityChanges,\n skippedLayers,\n },\n };\n }\n\n /**\n * Analyze coverage changes across layers\n */\n private analyzeCoverage(\n before: CoverageMetrics[],\n after: CoverageMetrics[],\n ): {\n comparison: Map<string, CoverageComparison>;\n skipped: SkippedLayer[];\n } {\n const comparison = new Map<string, CoverageComparison>();\n const skipped: SkippedLayer[] = [];\n\n // Create lookup maps for before and after states\n const beforeMap = new Map(before.map((c) => [c.layer, c]));\n const afterMap = new Map(after.map((c) => [c.layer, c]));\n\n // Check for layers only in \"before\"\n for (const beforeCoverage of before) {\n if (!afterMap.has(beforeCoverage.layer)) {\n skipped.push({\n layer: beforeCoverage.layer,\n reason: \"only-in-before\",\n coverage: beforeCoverage,\n });\n }\n }\n\n for (const afterCoverage of after) {\n const beforeCoverage = beforeMap.get(afterCoverage.layer);\n if (!beforeCoverage) {\n // New layer in after state - track as skipped\n skipped.push({\n layer: afterCoverage.layer,\n reason: \"only-in-after\",\n coverage: afterCoverage,\n });\n continue;\n }\n\n const deltas = {\n isolationChange:\n afterCoverage.isolationPercentage -\n beforeCoverage.isolationPercentage,\n densityChange:\n afterCoverage.relationshipsPerNodeType -\n beforeCoverage.relationshipsPerNodeType,\n utilizationChange:\n afterCoverage.utilizationPercentage -\n beforeCoverage.utilizationPercentage,\n nodeTypeCountChange:\n afterCoverage.nodeTypeCount - beforeCoverage.nodeTypeCount,\n relationshipCountChange:\n afterCoverage.relationshipCount - beforeCoverage.relationshipCount,\n };\n\n const improvements: string[] = [];\n const regressions: string[] = [];\n\n // Analyze changes\n if (deltas.isolationChange < -5) {\n improvements.push(\n `Isolation reduced by ${Math.abs(deltas.isolationChange).toFixed(1)}%`,\n );\n } else if (deltas.isolationChange > 5) {\n regressions.push(\n `Isolation increased by ${deltas.isolationChange.toFixed(1)}%`,\n );\n }\n\n if (deltas.densityChange > 0.5) {\n improvements.push(\n `Density increased by ${deltas.densityChange.toFixed(2)}`,\n );\n } else if (deltas.densityChange < -0.5) {\n regressions.push(\n `Density decreased by ${Math.abs(deltas.densityChange).toFixed(2)}`,\n );\n }\n\n if (deltas.utilizationChange > 5) {\n improvements.push(\n `Predicate utilization increased by ${deltas.utilizationChange.toFixed(1)}%`,\n );\n } else if (deltas.utilizationChange < -5) {\n regressions.push(\n `Predicate utilization decreased by ${Math.abs(deltas.utilizationChange).toFixed(1)}%`,\n );\n }\n\n comparison.set(afterCoverage.layer, {\n layer: afterCoverage.layer,\n before: beforeCoverage,\n after: afterCoverage,\n deltas,\n improvements,\n regressions,\n });\n }\n\n return { comparison, skipped };\n }\n\n /**\n * Analyze gap changes\n */\n private analyzeGaps(\n before: GapCandidate[],\n after: GapCandidate[],\n ): GapChanges {\n // Create gap signatures for comparison\n const beforeSigs = new Set(\n before.map((g) => this.gapSignature(g)),\n );\n const afterSigs = new Set(after.map((g) => this.gapSignature(g)));\n\n const resolved = before.filter(\n (g) => !afterSigs.has(this.gapSignature(g)),\n );\n const newGaps = after.filter(\n (g) => !beforeSigs.has(this.gapSignature(g)),\n );\n const persistent = after.filter((g) =>\n beforeSigs.has(this.gapSignature(g)),\n );\n\n const resolutionRate =\n before.length > 0 ? (resolved.length / before.length) * 100 : 0;\n\n return {\n before,\n after,\n resolved,\n newGaps,\n persistent,\n resolutionRate,\n };\n }\n\n /**\n * Generate gap signature for comparison\n */\n private gapSignature(gap: GapCandidate): string {\n return `${gap.sourceNodeType}:${gap.destinationNodeType}:${gap.suggestedPredicate}`;\n }\n\n /**\n * Analyze duplicate changes\n */\n private analyzeDuplicates(\n before: DuplicateCandidate[],\n after: DuplicateCandidate[],\n ): DuplicateChanges {\n const beforeSigs = new Set(\n before.map((d) => this.duplicateSignature(d)),\n );\n const afterSigs = new Set(\n after.map((d) => this.duplicateSignature(d)),\n );\n\n const resolved = before.filter(\n (d) => !afterSigs.has(this.duplicateSignature(d)),\n );\n const newDuplicates = after.filter(\n (d) => !beforeSigs.has(this.duplicateSignature(d)),\n );\n const persistent = after.filter((d) =>\n beforeSigs.has(this.duplicateSignature(d)),\n );\n\n const eliminationRate =\n before.length > 0 ? (resolved.length / before.length) * 100 : 0;\n\n return {\n before,\n after,\n resolved,\n newDuplicates,\n persistent,\n eliminationRate,\n };\n }\n\n /**\n * Generate duplicate signature for comparison\n */\n private duplicateSignature(dup: DuplicateCandidate): string {\n // Sort relationship IDs for consistent comparison\n const sorted = [...dup.relationships].sort();\n return `${sorted[0]}:${sorted[1]}`;\n }\n\n /**\n * Analyze balance changes\n */\n private analyzeBalance(\n before: BalanceAssessment[],\n after: BalanceAssessment[],\n ): BalanceChanges {\n const beforeMap = new Map(before.map((b) => [b.nodeType, b]));\n\n const improvements: BalanceAssessment[] = [];\n const regressions: BalanceAssessment[] = [];\n const newlyBalanced: BalanceAssessment[] = [];\n\n for (const afterAssessment of after) {\n const beforeAssessment = beforeMap.get(afterAssessment.nodeType);\n if (!beforeAssessment) {\n continue;\n }\n\n // Check if moved toward balanced\n const beforeDistance = this.distanceFromBalance(beforeAssessment);\n const afterDistance = this.distanceFromBalance(afterAssessment);\n\n if (afterDistance < beforeDistance) {\n improvements.push(afterAssessment);\n } else if (afterDistance > beforeDistance) {\n regressions.push(afterAssessment);\n }\n\n // Check if newly balanced\n if (\n beforeAssessment.status !== \"balanced\" &&\n afterAssessment.status === \"balanced\"\n ) {\n newlyBalanced.push(afterAssessment);\n }\n }\n\n return {\n before,\n after,\n improvements,\n regressions,\n newlyBalanced,\n };\n }\n\n /**\n * Calculate distance from balanced state\n */\n private distanceFromBalance(assessment: BalanceAssessment): number {\n const [min, max] = assessment.targetRange;\n const target = (min + max) / 2;\n return Math.abs(assessment.currentCount - target);\n }\n\n /**\n * Analyze connectivity changes\n */\n private analyzeConnectivity(\n before: AuditReport[\"connectivity\"],\n after: AuditReport[\"connectivity\"],\n ): ConnectivityComparison {\n const beforeStats = {\n componentCount: before.components.length,\n isolatedNodes: before.stats.isolatedNodes,\n averageDegree: before.stats.averageDegree,\n };\n\n const afterStats = {\n componentCount: after.components.length,\n isolatedNodes: after.stats.isolatedNodes,\n averageDegree: after.stats.averageDegree,\n };\n\n return {\n before: beforeStats,\n after: afterStats,\n deltas: {\n componentChange: afterStats.componentCount - beforeStats.componentCount,\n isolationChange: afterStats.isolatedNodes - beforeStats.isolatedNodes,\n degreeChange: afterStats.averageDegree - beforeStats.averageDegree,\n },\n };\n }\n\n /**\n * Generate summary report\n */\n private generateSummary(\n timestamp: string,\n coverageComparison: Map<string, CoverageComparison>,\n gapChanges: GapChanges,\n duplicateChanges: DuplicateChanges,\n balanceChanges: BalanceChanges,\n ): SummaryReport {\n const coverageChanges = Array.from(coverageComparison.values()).map(\n (comp) => ({\n layer: comp.layer,\n before: {\n isolation: comp.before.isolationPercentage,\n density: comp.before.relationshipsPerNodeType,\n },\n after: {\n isolation: comp.after.isolationPercentage,\n density: comp.after.relationshipsPerNodeType,\n },\n delta: {\n isolation: comp.deltas.isolationChange,\n density: comp.deltas.densityChange,\n },\n }),\n );\n\n // Calculate total relationships added\n const relationshipsAdded = Array.from(coverageComparison.values()).reduce(\n (sum, comp) => sum + comp.deltas.relationshipCountChange,\n 0,\n );\n\n // Generate balance improvement descriptions\n const balanceImprovements = balanceChanges.newlyBalanced.map(\n (b) => `${b.nodeType} achieved balanced density (${b.currentCount} relationships)`,\n );\n\n return {\n timestamp,\n coverageChanges,\n relationshipsAdded: Math.max(0, relationshipsAdded), // Only count additions\n gapsResolved: gapChanges.resolved.length,\n remainingGaps: gapChanges.after.length,\n duplicatesResolved: duplicateChanges.resolved.length,\n balanceImprovements,\n };\n }\n}\n"],
5
+ "mappings": "AAuHM,MAAO,qBAAoB;;;;EAI/B,QAAQ,QAAqB,OAAkB;AAC7C,UAAM,EAAE,YAAY,oBAAoB,SAAS,cAAa,IAC5D,KAAK,gBAAgB,OAAO,UAA+B,MAAM,QAA6B,GAC1F,aAAa,KAAK,YAAY,OAAO,MAAwB,MAAM,IAAsB,GACzF,mBAAmB,KAAK,kBAC5B,OAAO,YACP,MAAM,UAAkC,GAEpC,iBAAiB,KAAK,eAAe,OAAO,SAAgC,MAAM,OAA8B,GAChH,sBAAsB,KAAK,oBAC/B,OAAO,cACP,MAAM,YAAY;AAWpB,WAAO;MACL,SATc,KAAK,gBACnB,MAAM,WACN,oBACA,YACA,kBACA,cAAc;MAKd,UAAU;QACR,iBAAiB;QACjB;QACA;QACA;QACA;QACA;;;EAGN;;;;EAKQ,gBACN,QACA,OAAwB;AAKxB,UAAM,aAAa,oBAAI,IAAG,GACpB,UAA0B,CAAA,GAG1B,YAAY,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GACnD,WAAW,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAGvD,eAAW,kBAAkB;AAC3B,MAAK,SAAS,IAAI,eAAe,KAAK,KACpC,QAAQ,KAAK;QACX,OAAO,eAAe;QACtB,QAAQ;QACR,UAAU;OACX;AAIL,eAAW,iBAAiB,OAAO;AACjC,YAAM,iBAAiB,UAAU,IAAI,cAAc,KAAK;AACxD,UAAI,CAAC,gBAAgB;AAEnB,gBAAQ,KAAK;UACX,OAAO,cAAc;UACrB,QAAQ;UACR,UAAU;SACX;AACD;MACF;AAEA,YAAM,SAAS;QACb,iBACE,cAAc,sBACd,eAAe;QACjB,eACE,cAAc,2BACd,eAAe;QACjB,mBACE,cAAc,wBACd,eAAe;QACjB,qBACE,cAAc,gBAAgB,eAAe;QAC/C,yBACE,cAAc,oBAAoB,eAAe;SAG/C,eAAyB,CAAA,GACzB,cAAwB,CAAA;AAG9B,MAAI,OAAO,kBAAkB,KAC3B,aAAa,KACX,wBAAwB,KAAK,IAAI,OAAO,eAAe,EAAE,QAAQ,CAAC,CAAC,GAAG,IAE/D,OAAO,kBAAkB,KAClC,YAAY,KACV,0BAA0B,OAAO,gBAAgB,QAAQ,CAAC,CAAC,GAAG,GAI9D,OAAO,gBAAgB,MACzB,aAAa,KACX,wBAAwB,OAAO,cAAc,QAAQ,CAAC,CAAC,EAAE,IAElD,OAAO,gBAAgB,QAChC,YAAY,KACV,wBAAwB,KAAK,IAAI,OAAO,aAAa,EAAE,QAAQ,CAAC,CAAC,EAAE,GAInE,OAAO,oBAAoB,IAC7B,aAAa,KACX,sCAAsC,OAAO,kBAAkB,QAAQ,CAAC,CAAC,GAAG,IAErE,OAAO,oBAAoB,MACpC,YAAY,KACV,sCAAsC,KAAK,IAAI,OAAO,iBAAiB,EAAE,QAAQ,CAAC,CAAC,GAAG,GAI1F,WAAW,IAAI,cAAc,OAAO;QAClC,OAAO,cAAc;QACrB,QAAQ;QACR,OAAO;QACP;QACA;QACA;OACD;IACH;AAEA,WAAO,EAAE,YAAY,QAAO;EAC9B;;;;EAKQ,YACN,QACA,OAAqB;AAGrB,UAAM,aAAa,IAAI,IACrB,OAAO,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,GAEnC,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,GAE1D,WAAW,OAAO,OACtB,CAAC,MAAM,CAAC,UAAU,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,GAEvC,UAAU,MAAM,OACpB,CAAC,MAAM,CAAC,WAAW,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,GAExC,aAAa,MAAM,OAAO,CAAC,MAC/B,WAAW,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,GAGhC,iBACJ,OAAO,SAAS,IAAK,SAAS,SAAS,OAAO,SAAU,MAAM;AAEhE,WAAO;MACL;MACA;MACA;MACA;MACA;MACA;;EAEJ;;;;EAKQ,aAAa,KAAiB;AACpC,WAAO,GAAG,IAAI,cAAc,IAAI,IAAI,mBAAmB,IAAI,IAAI,kBAAkB;EACnF;;;;EAKQ,kBACN,QACA,OAA2B;AAE3B,UAAM,aAAa,IAAI,IACrB,OAAO,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAEzC,YAAY,IAAI,IACpB,MAAM,IAAI,CAAC,MAAM,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAGxC,WAAW,OAAO,OACtB,CAAC,MAAM,CAAC,UAAU,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAE7C,gBAAgB,MAAM,OAC1B,CAAC,MAAM,CAAC,WAAW,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAE9C,aAAa,MAAM,OAAO,CAAC,MAC/B,WAAW,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAGtC,kBACJ,OAAO,SAAS,IAAK,SAAS,SAAS,OAAO,SAAU,MAAM;AAEhE,WAAO;MACL;MACA;MACA;MACA;MACA;MACA;;EAEJ;;;;EAKQ,mBAAmB,KAAuB;AAEhD,UAAM,SAAS,CAAC,GAAG,IAAI,aAAa,EAAE,KAAI;AAC1C,WAAO,GAAG,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;EAClC;;;;EAKQ,eACN,QACA,OAA0B;AAE1B,UAAM,YAAY,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAEtD,eAAoC,CAAA,GACpC,cAAmC,CAAA,GACnC,gBAAqC,CAAA;AAE3C,eAAW,mBAAmB,OAAO;AACnC,YAAM,mBAAmB,UAAU,IAAI,gBAAgB,QAAQ;AAC/D,UAAI,CAAC;AACH;AAIF,YAAM,iBAAiB,KAAK,oBAAoB,gBAAgB,GAC1D,gBAAgB,KAAK,oBAAoB,eAAe;AAE9D,MAAI,gBAAgB,iBAClB,aAAa,KAAK,eAAe,IACxB,gBAAgB,kBACzB,YAAY,KAAK,eAAe,GAKhC,iBAAiB,WAAW,cAC5B,gBAAgB,WAAW,cAE3B,cAAc,KAAK,eAAe;IAEtC;AAEA,WAAO;MACL;MACA;MACA;MACA;MACA;;EAEJ;;;;EAKQ,oBAAoB,YAA6B;AACvD,UAAM,CAAC,KAAK,GAAG,IAAI,WAAW,aACxB,UAAU,MAAM,OAAO;AAC7B,WAAO,KAAK,IAAI,WAAW,eAAe,MAAM;EAClD;;;;EAKQ,oBACN,QACA,OAAkC;AAElC,UAAM,cAAc;MAClB,gBAAgB,OAAO,WAAW;MAClC,eAAe,OAAO,MAAM;MAC5B,eAAe,OAAO,MAAM;OAGxB,aAAa;MACjB,gBAAgB,MAAM,WAAW;MACjC,eAAe,MAAM,MAAM;MAC3B,eAAe,MAAM,MAAM;;AAG7B,WAAO;MACL,QAAQ;MACR,OAAO;MACP,QAAQ;QACN,iBAAiB,WAAW,iBAAiB,YAAY;QACzD,iBAAiB,WAAW,gBAAgB,YAAY;QACxD,cAAc,WAAW,gBAAgB,YAAY;;;EAG3D;;;;EAKQ,gBACN,WACA,oBACA,YACA,kBACA,gBAA8B;AAE9B,UAAM,kBAAkB,MAAM,KAAK,mBAAmB,OAAM,CAAE,EAAE,IAC9D,CAAC,UAAU;MACT,OAAO,KAAK;MACZ,QAAQ;QACN,WAAW,KAAK,OAAO;QACvB,SAAS,KAAK,OAAO;;MAEvB,OAAO;QACL,WAAW,KAAK,MAAM;QACtB,SAAS,KAAK,MAAM;;MAEtB,OAAO;QACL,WAAW,KAAK,OAAO;QACvB,SAAS,KAAK,OAAO;;MAEvB,GAIE,qBAAqB,MAAM,KAAK,mBAAmB,OAAM,CAAE,EAAE,OACjE,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,yBACjC,CAAC,GAIG,sBAAsB,eAAe,cAAc,IACvD,CAAC,MAAM,GAAG,EAAE,QAAQ,+BAA+B,EAAE,YAAY,iBAAiB;AAGpF,WAAO;MACL;MACA;MACA,oBAAoB,KAAK,IAAI,GAAG,kBAAkB;;MAClD,cAAc,WAAW,SAAS;MAClC,eAAe,WAAW,MAAM;MAChC,oBAAoB,iBAAiB,SAAS;MAC9C;;EAEJ;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ import { CoverageAnalyzer } from "./relationships/analysis/coverage-analyzer.js";
2
+ import { DuplicateDetector } from "./relationships/analysis/duplicate-detector.js";
3
+ import { GapAnalyzer } from "./relationships/analysis/gap-analyzer.js";
4
+ import { BalanceAssessor } from "./relationships/analysis/balance-assessor.js";
5
+ import { RelationshipGraph } from "./relationships/graph/relationship-graph.js";
6
+ import { ConnectivityAnalyzer } from "./relationships/graph/connectivity.js";
7
+ import { SnapshotStorage } from "./snapshot-storage.js";
8
+ import { DifferentialAnalyzer } from "./differential-analyzer.js";
9
+ import { AuditAIRunner } from "./ai/runner.js";
10
+ import { PromptTemplates } from "./relationships/ai/prompts.js";
11
+ import { ResponseParser } from "./relationships/ai/parser.js";
12
+ import { AIEvaluator, InMemoryProgressTracker } from "./relationships/ai/evaluator.js";
13
+ import { AuditOrchestrator } from "./relationships/spec/orchestrator.js";
14
+ import { ModelAuditOrchestrator } from "./relationships/model/orchestrator.js";
15
+ export {
16
+ AIEvaluator,
17
+ AuditAIRunner,
18
+ AuditOrchestrator,
19
+ BalanceAssessor,
20
+ ConnectivityAnalyzer,
21
+ CoverageAnalyzer,
22
+ DifferentialAnalyzer,
23
+ DuplicateDetector,
24
+ GapAnalyzer,
25
+ InMemoryProgressTracker,
26
+ ModelAuditOrchestrator,
27
+ PromptTemplates,
28
+ RelationshipGraph,
29
+ ResponseParser,
30
+ SnapshotStorage
31
+ };
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/audit/index.ts"],
4
+ "sourcesContent": ["/**\n * Relationship Audit System - Public API\n *\n * Exports all audit analysis components and types.\n */\n\n// Type definitions\nexport type {\n CoverageMetrics,\n DuplicateCandidate,\n GapCandidate,\n BalanceAssessment,\n ConnectedComponent,\n NodeDegree,\n TransitiveChain,\n SummaryReport,\n AuditReport,\n ConnectivityStats,\n LayerData,\n} from \"./types.js\";\n\n// Analysis components\nexport { CoverageAnalyzer } from \"./relationships/analysis/coverage-analyzer.js\";\nexport { DuplicateDetector } from \"./relationships/analysis/duplicate-detector.js\";\nexport { GapAnalyzer } from \"./relationships/analysis/gap-analyzer.js\";\nexport type { GapAnalysisResult } from \"./relationships/analysis/gap-analyzer.js\";\nexport { BalanceAssessor } from \"./relationships/analysis/balance-assessor.js\";\n\n// Graph components\nexport { RelationshipGraph } from \"./relationships/graph/relationship-graph.js\";\nexport { ConnectivityAnalyzer } from \"./relationships/graph/connectivity.js\";\n\n// Snapshot and differential analysis components\nexport { SnapshotStorage } from \"./snapshot-storage.js\";\nexport type { SnapshotMetadata, SnapshotStorageConfig } from \"./snapshot-storage.js\";\nexport { DifferentialAnalyzer } from \"./differential-analyzer.js\";\nexport type {\n DifferentialAnalysis,\n CoverageComparison,\n GapChanges,\n DuplicateChanges,\n BalanceChanges,\n ConnectivityComparison,\n SkippedLayer,\n} from \"./differential-analyzer.js\";\n\n// AI evaluation components\nexport { AuditAIRunner } from \"./ai/runner.js\";\nexport { PromptTemplates } from \"./relationships/ai/prompts.js\";\nexport { ResponseParser } from \"./relationships/ai/parser.js\";\nexport type {\n RelationshipRecommendation,\n LayerReview,\n InterLayerValidation,\n} from \"./relationships/ai/parser.js\";\nexport { AIEvaluator, InMemoryProgressTracker } from \"./relationships/ai/evaluator.js\";\nexport type { ProgressTracker, AIEvaluationConfig } from \"./relationships/ai/evaluator.js\";\n\n// Spec relationship orchestrator\nexport { AuditOrchestrator } from \"./relationships/spec/orchestrator.js\";\nexport type { AuditOptions, AuditComponents } from \"./relationships/spec/orchestrator.js\";\n\n// Model relationship orchestrator\nexport { ModelAuditOrchestrator } from \"./relationships/model/orchestrator.js\";\nexport type { ModelAuditOptions } from \"./relationships/model/orchestrator.js\";\n"],
5
+ "mappings": "AAsBA,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAE5B,SAAS,uBAAuB;AAGhC,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AAGrC,SAAS,uBAAuB;AAEhC,SAAS,4BAA4B;AAYrC,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAM/B,SAAS,aAAa,+BAA+B;AAIrD,SAAS,yBAAyB;AAIlC,SAAS,8BAA8B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,49 @@
1
+ import { NodePromptTemplates } from "./prompts.js";
2
+ import { NodeResponseParser } from "./parser.js";
3
+ import { AuditAIRunner, AIEvaluationAbortError } from "../../ai/runner.js";
4
+ import { getErrorMessage } from "../../../utils/errors.js";
5
+ const INVOKE_TIMEOUT_MS = 5 * 60 * 1e3;
6
+ class NodeAIEvaluator {
7
+ runner;
8
+ promptTemplates;
9
+ responseParser;
10
+ constructor() {
11
+ this.runner = new AuditAIRunner(), this.promptTemplates = new NodePromptTemplates(), this.responseParser = new NodeResponseParser();
12
+ }
13
+ /**
14
+ * Evaluate each layer sequentially, returning one LayerAIReview per layer.
15
+ * Layers with zero schemas are skipped.
16
+ * Fails fast after maxConsecutiveFailures consecutive Claude invocation failures.
17
+ */
18
+ async evaluateLayers(layerDefs, schemasByLayer) {
19
+ const reviews = [];
20
+ for (const layerDef of layerDefs) {
21
+ const schemas = schemasByLayer.get(layerDef.id) ?? [];
22
+ if (schemas.length === 0)
23
+ continue;
24
+ const standard = layerDef.inspiredBy ? `${layerDef.inspiredBy.standard} ${layerDef.inspiredBy.version}` : this.promptTemplates.getFallbackStandard(layerDef.id);
25
+ process.stderr.write(` Evaluating layer: ${layerDef.id} (${schemas.length} node types)...
26
+ `);
27
+ try {
28
+ const prompt = this.promptTemplates.layerEvaluation({ layerDef, schemas }), response = await this.runner.invoke(prompt, `layer: ${layerDef.id}`, INVOKE_TIMEOUT_MS), nodeEvaluations = this.responseParser.parseLayerEvaluation(response), avgAlignmentScore = nodeEvaluations.length > 0 ? nodeEvaluations.reduce((sum, e) => sum + e.alignmentScore, 0) / nodeEvaluations.length : 0, avgDocumentationScore = nodeEvaluations.length > 0 ? nodeEvaluations.reduce((sum, e) => sum + e.documentationScore, 0) / nodeEvaluations.length : 0;
29
+ reviews.push({
30
+ layerId: layerDef.id,
31
+ standard,
32
+ nodeEvaluations,
33
+ avgAlignmentScore: Math.round(avgAlignmentScore * 10) / 10,
34
+ avgDocumentationScore: Math.round(avgDocumentationScore * 10) / 10
35
+ });
36
+ } catch (error) {
37
+ const msg = getErrorMessage(error);
38
+ if (process.stderr.write(` \u26A0\uFE0F Failed to evaluate layer ${layerDef.id}: ${msg}
39
+ `), error instanceof AIEvaluationAbortError)
40
+ throw error;
41
+ }
42
+ }
43
+ return reviews;
44
+ }
45
+ }
46
+ export {
47
+ NodeAIEvaluator
48
+ };
49
+ //# sourceMappingURL=evaluator.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/nodes/ai/evaluator.ts"],
4
+ "sourcesContent": ["import type { LayerDefinition, ParsedNodeSchema, LayerAIReview } from \"../types.js\";\nimport { NodePromptTemplates } from \"./prompts.js\";\nimport { NodeResponseParser } from \"./parser.js\";\nimport { AuditAIRunner, AIEvaluationAbortError } from \"../../ai/runner.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\n\nconst INVOKE_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes per invocation\n\nexport class NodeAIEvaluator {\n private readonly runner: AuditAIRunner;\n private readonly promptTemplates: NodePromptTemplates;\n private readonly responseParser: NodeResponseParser;\n\n constructor() {\n this.runner = new AuditAIRunner();\n this.promptTemplates = new NodePromptTemplates();\n this.responseParser = new NodeResponseParser();\n }\n\n /**\n * Evaluate each layer sequentially, returning one LayerAIReview per layer.\n * Layers with zero schemas are skipped.\n * Fails fast after maxConsecutiveFailures consecutive Claude invocation failures.\n */\n async evaluateLayers(\n layerDefs: LayerDefinition[],\n schemasByLayer: Map<string, ParsedNodeSchema[]>\n ): Promise<LayerAIReview[]> {\n const reviews: LayerAIReview[] = [];\n\n for (const layerDef of layerDefs) {\n const schemas = schemasByLayer.get(layerDef.id) ?? [];\n if (schemas.length === 0) {\n continue;\n }\n\n const standard = layerDef.inspiredBy\n ? `${layerDef.inspiredBy.standard} ${layerDef.inspiredBy.version}`\n : this.promptTemplates.getFallbackStandard(layerDef.id);\n\n process.stderr.write(` Evaluating layer: ${layerDef.id} (${schemas.length} node types)...\\n`);\n\n try {\n const prompt = this.promptTemplates.layerEvaluation({ layerDef, schemas });\n const response = await this.runner.invoke(prompt, `layer: ${layerDef.id}`, INVOKE_TIMEOUT_MS);\n const nodeEvaluations = this.responseParser.parseLayerEvaluation(response);\n\n const avgAlignmentScore =\n nodeEvaluations.length > 0\n ? nodeEvaluations.reduce((sum, e) => sum + e.alignmentScore, 0) / nodeEvaluations.length\n : 0;\n const avgDocumentationScore =\n nodeEvaluations.length > 0\n ? nodeEvaluations.reduce((sum, e) => sum + e.documentationScore, 0) /\n nodeEvaluations.length\n : 0;\n\n reviews.push({\n layerId: layerDef.id,\n standard,\n nodeEvaluations,\n avgAlignmentScore: Math.round(avgAlignmentScore * 10) / 10,\n avgDocumentationScore: Math.round(avgDocumentationScore * 10) / 10,\n });\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n process.stderr.write(` \u26A0\uFE0F Failed to evaluate layer ${layerDef.id}: ${msg}\\n`);\n\n if (error instanceof AIEvaluationAbortError) {\n throw error;\n }\n }\n }\n\n return reviews;\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,2BAA2B;AACpC,SAAS,0BAA0B;AACnC,SAAS,eAAe,8BAA8B;AACtD,SAAS,uBAAuB;AAEhC,MAAM,oBAAoB,IAAI,KAAK;AAE7B,MAAO,gBAAe;EACT;EACA;EACA;EAEjB,cAAA;AACE,SAAK,SAAS,IAAI,cAAa,GAC/B,KAAK,kBAAkB,IAAI,oBAAmB,GAC9C,KAAK,iBAAiB,IAAI,mBAAkB;EAC9C;;;;;;EAOA,MAAM,eACJ,WACA,gBAA+C;AAE/C,UAAM,UAA2B,CAAA;AAEjC,eAAW,YAAY,WAAW;AAChC,YAAM,UAAU,eAAe,IAAI,SAAS,EAAE,KAAK,CAAA;AACnD,UAAI,QAAQ,WAAW;AACrB;AAGF,YAAM,WAAW,SAAS,aACtB,GAAG,SAAS,WAAW,QAAQ,IAAI,SAAS,WAAW,OAAO,KAC9D,KAAK,gBAAgB,oBAAoB,SAAS,EAAE;AAExD,cAAQ,OAAO,MAAM,uBAAuB,SAAS,EAAE,KAAK,QAAQ,MAAM;CAAmB;AAE7F,UAAI;AACF,cAAM,SAAS,KAAK,gBAAgB,gBAAgB,EAAE,UAAU,QAAO,CAAE,GACnE,WAAW,MAAM,KAAK,OAAO,OAAO,QAAQ,UAAU,SAAS,EAAE,IAAI,iBAAiB,GACtF,kBAAkB,KAAK,eAAe,qBAAqB,QAAQ,GAEnE,oBACJ,gBAAgB,SAAS,IACrB,gBAAgB,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,gBAAgB,CAAC,IAAI,gBAAgB,SAChF,GACA,wBACJ,gBAAgB,SAAS,IACrB,gBAAgB,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,oBAAoB,CAAC,IAChE,gBAAgB,SAChB;AAEN,gBAAQ,KAAK;UACX,SAAS,SAAS;UAClB;UACA;UACA,mBAAmB,KAAK,MAAM,oBAAoB,EAAE,IAAI;UACxD,uBAAuB,KAAK,MAAM,wBAAwB,EAAE,IAAI;SACjE;MACH,SAAS,OAAgB;AACvB,cAAM,MAAM,gBAAgB,KAAK;AAGjC,YAFA,QAAQ,OAAO,MAAM,4CAAkC,SAAS,EAAE,KAAK,GAAG;CAAI,GAE1E,iBAAiB;AACnB,gBAAM;MAEV;IACF;AAEA,WAAO;EACT;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,55 @@
1
+ import { getErrorMessage } from "../../../utils/errors.js";
2
+ class NodeResponseParser {
3
+ /**
4
+ * Parse NodeAIEvaluation[] from a Claude response string.
5
+ * Tries code-fenced JSON first, falls back to raw array extraction.
6
+ */
7
+ parseLayerEvaluation(response) {
8
+ const codeBlockMatch = response.match(/```json\n([\s\S]*?)\n```/), rawArrayMatch = response.match(/\[[\s\S]*\]/), jsonMatch = codeBlockMatch ?? rawArrayMatch;
9
+ if (!jsonMatch) {
10
+ const truncated = response.substring(0, 200);
11
+ throw new Error(`Failed to extract JSON array from AI response. Expected JSON array in code block or raw JSON array.
12
+ Received: ${truncated}${response.length > 200 ? "..." : ""}`);
13
+ }
14
+ const jsonString = codeBlockMatch ? codeBlockMatch[1] : jsonMatch[0];
15
+ let parsed;
16
+ try {
17
+ parsed = JSON.parse(jsonString);
18
+ } catch (error) {
19
+ const truncated = jsonString.substring(0, 200);
20
+ throw new Error(`Failed to parse JSON from AI response: ${getErrorMessage(error)}
21
+ Received: ${truncated}${jsonString.length > 200 ? "..." : ""}`);
22
+ }
23
+ if (!Array.isArray(parsed))
24
+ throw new Error("Expected JSON array of node evaluations from AI response");
25
+ return parsed.map((item, index) => this.validateItem(item, index));
26
+ }
27
+ validateItem(item, index) {
28
+ if (typeof item != "object" || item === null)
29
+ throw new Error(`Node evaluation at index ${index} is not a valid object`);
30
+ const obj = item;
31
+ if (!obj.specNodeId || typeof obj.specNodeId != "string")
32
+ throw new Error(`Node evaluation at index ${index} missing or invalid field: specNodeId (must be non-empty string)`);
33
+ if (typeof obj.alignmentScore != "number")
34
+ throw new Error(`Node evaluation at index ${index} missing or invalid field: alignmentScore (must be number)`);
35
+ if (typeof obj.documentationScore != "number")
36
+ throw new Error(`Node evaluation at index ${index} missing or invalid field: documentationScore (must be number)`);
37
+ if (!obj.alignmentReasoning || typeof obj.alignmentReasoning != "string")
38
+ throw new Error(`Node evaluation at index ${index} missing or invalid field: alignmentReasoning (must be non-empty string)`);
39
+ if (!obj.documentationReasoning || typeof obj.documentationReasoning != "string")
40
+ throw new Error(`Node evaluation at index ${index} missing or invalid field: documentationReasoning (must be non-empty string)`);
41
+ const suggestions = Array.isArray(obj.suggestions) && obj.suggestions.every((s) => typeof s == "string") ? obj.suggestions : [];
42
+ return {
43
+ specNodeId: obj.specNodeId,
44
+ alignmentScore: Math.max(0, Math.min(100, Math.round(obj.alignmentScore))),
45
+ alignmentReasoning: obj.alignmentReasoning,
46
+ documentationScore: Math.max(0, Math.min(100, Math.round(obj.documentationScore))),
47
+ documentationReasoning: obj.documentationReasoning,
48
+ suggestions
49
+ };
50
+ }
51
+ }
52
+ export {
53
+ NodeResponseParser
54
+ };
55
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/nodes/ai/parser.ts"],
4
+ "sourcesContent": ["import type { NodeAIEvaluation } from \"../types.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\n\nexport class NodeResponseParser {\n /**\n * Parse NodeAIEvaluation[] from a Claude response string.\n * Tries code-fenced JSON first, falls back to raw array extraction.\n */\n parseLayerEvaluation(response: string): NodeAIEvaluation[] {\n // 1. Try code block: ```json\\n...\\n```\n const codeBlockMatch = response.match(/```json\\n([\\s\\S]*?)\\n```/);\n // 2. Fall back to raw array\n const rawArrayMatch = response.match(/\\[[\\s\\S]*\\]/);\n\n const jsonMatch = codeBlockMatch ?? rawArrayMatch;\n if (!jsonMatch) {\n const truncated = response.substring(0, 200);\n throw new Error(\n `Failed to extract JSON array from AI response. Expected JSON array in code block or raw JSON array.\\nReceived: ${truncated}${response.length > 200 ? \"...\" : \"\"}`\n );\n }\n\n const jsonString = codeBlockMatch ? codeBlockMatch[1] : jsonMatch[0];\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonString);\n } catch (error: unknown) {\n const truncated = jsonString.substring(0, 200);\n throw new Error(\n `Failed to parse JSON from AI response: ${getErrorMessage(error)}\\nReceived: ${truncated}${jsonString.length > 200 ? \"...\" : \"\"}`\n );\n }\n\n if (!Array.isArray(parsed)) {\n throw new Error(\"Expected JSON array of node evaluations from AI response\");\n }\n\n return parsed.map((item: unknown, index: number) => this.validateItem(item, index));\n }\n\n private validateItem(item: unknown, index: number): NodeAIEvaluation {\n if (typeof item !== \"object\" || item === null) {\n throw new Error(`Node evaluation at index ${index} is not a valid object`);\n }\n\n const obj = item as Record<string, unknown>;\n\n if (!obj.specNodeId || typeof obj.specNodeId !== \"string\") {\n throw new Error(\n `Node evaluation at index ${index} missing or invalid field: specNodeId (must be non-empty string)`\n );\n }\n\n if (typeof obj.alignmentScore !== \"number\") {\n throw new Error(\n `Node evaluation at index ${index} missing or invalid field: alignmentScore (must be number)`\n );\n }\n\n if (typeof obj.documentationScore !== \"number\") {\n throw new Error(\n `Node evaluation at index ${index} missing or invalid field: documentationScore (must be number)`\n );\n }\n\n if (!obj.alignmentReasoning || typeof obj.alignmentReasoning !== \"string\") {\n throw new Error(\n `Node evaluation at index ${index} missing or invalid field: alignmentReasoning (must be non-empty string)`\n );\n }\n\n if (!obj.documentationReasoning || typeof obj.documentationReasoning !== \"string\") {\n throw new Error(\n `Node evaluation at index ${index} missing or invalid field: documentationReasoning (must be non-empty string)`\n );\n }\n\n const suggestions = Array.isArray(obj.suggestions) &&\n obj.suggestions.every((s) => typeof s === \"string\")\n ? (obj.suggestions as string[])\n : [];\n\n return {\n specNodeId: obj.specNodeId,\n alignmentScore: Math.max(0, Math.min(100, Math.round(obj.alignmentScore))),\n alignmentReasoning: obj.alignmentReasoning,\n documentationScore: Math.max(0, Math.min(100, Math.round(obj.documentationScore))),\n documentationReasoning: obj.documentationReasoning,\n suggestions,\n };\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,uBAAuB;AAE1B,MAAO,mBAAkB;;;;;EAK7B,qBAAqB,UAAgB;AAEnC,UAAM,iBAAiB,SAAS,MAAM,0BAA0B,GAE1D,gBAAgB,SAAS,MAAM,aAAa,GAE5C,YAAY,kBAAkB;AACpC,QAAI,CAAC,WAAW;AACd,YAAM,YAAY,SAAS,UAAU,GAAG,GAAG;AAC3C,YAAM,IAAI,MACR;YAAkH,SAAS,GAAG,SAAS,SAAS,MAAM,QAAQ,EAAE,EAAE;IAEtK;AAEA,UAAM,aAAa,iBAAiB,eAAe,CAAC,IAAI,UAAU,CAAC;AACnE,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,UAAU;IAChC,SAAS,OAAgB;AACvB,YAAM,YAAY,WAAW,UAAU,GAAG,GAAG;AAC7C,YAAM,IAAI,MACR,0CAA0C,gBAAgB,KAAK,CAAC;YAAe,SAAS,GAAG,WAAW,SAAS,MAAM,QAAQ,EAAE,EAAE;IAErI;AAEA,QAAI,CAAC,MAAM,QAAQ,MAAM;AACvB,YAAM,IAAI,MAAM,0DAA0D;AAG5E,WAAO,OAAO,IAAI,CAAC,MAAe,UAAkB,KAAK,aAAa,MAAM,KAAK,CAAC;EACpF;EAEQ,aAAa,MAAe,OAAa;AAC/C,QAAI,OAAO,QAAS,YAAY,SAAS;AACvC,YAAM,IAAI,MAAM,4BAA4B,KAAK,wBAAwB;AAG3E,UAAM,MAAM;AAEZ,QAAI,CAAC,IAAI,cAAc,OAAO,IAAI,cAAe;AAC/C,YAAM,IAAI,MACR,4BAA4B,KAAK,kEAAkE;AAIvG,QAAI,OAAO,IAAI,kBAAmB;AAChC,YAAM,IAAI,MACR,4BAA4B,KAAK,4DAA4D;AAIjG,QAAI,OAAO,IAAI,sBAAuB;AACpC,YAAM,IAAI,MACR,4BAA4B,KAAK,gEAAgE;AAIrG,QAAI,CAAC,IAAI,sBAAsB,OAAO,IAAI,sBAAuB;AAC/D,YAAM,IAAI,MACR,4BAA4B,KAAK,0EAA0E;AAI/G,QAAI,CAAC,IAAI,0BAA0B,OAAO,IAAI,0BAA2B;AACvE,YAAM,IAAI,MACR,4BAA4B,KAAK,8EAA8E;AAInH,UAAM,cAAc,MAAM,QAAQ,IAAI,WAAW,KAC/C,IAAI,YAAY,MAAM,CAAC,MAAM,OAAO,KAAM,QAAQ,IAC/C,IAAI,cACL,CAAA;AAEJ,WAAO;MACL,YAAY,IAAI;MAChB,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,cAAc,CAAC,CAAC;MACzE,oBAAoB,IAAI;MACxB,oBAAoB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,kBAAkB,CAAC,CAAC;MACjF,wBAAwB,IAAI;MAC5B;;EAEJ;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,103 @@
1
+ class NodePromptTemplates {
2
+ /**
3
+ * Build a per-layer batch prompt that asks Claude to evaluate every node type
4
+ * for alignment to the layer's inspiring standard and documentation quality.
5
+ */
6
+ layerEvaluation(context) {
7
+ const { layerDef, schemas } = context, standard = layerDef.inspiredBy ? `${layerDef.inspiredBy.standard} ${layerDef.inspiredBy.version}` : this.getFallbackStandard(layerDef.id), inputItems = schemas.map((s) => ({
8
+ specNodeId: s.specNodeId,
9
+ title: s.title,
10
+ description: s.description,
11
+ attributeNames: Object.keys(s.attributes.properties)
12
+ }));
13
+ return `You are evaluating node type definitions in a federated architecture specification.
14
+
15
+ Layer: ${layerDef.name} (layer ${layerDef.number})
16
+ Inspiring Standard: ${standard}
17
+
18
+ For each node type, score it on two dimensions (0-100 each):
19
+
20
+ ALIGNMENT SCORE \u2014 How well does this node type conceptually belong in the ${layerDef.name} layer as defined by ${standard}?
21
+ 90-100: Core concept in the standard, perfect fit for this layer
22
+ 70-89: Clearly related to the standard, well-placed in this layer
23
+ 50-69: Loosely related, could belong here or in an adjacent layer
24
+ 30-49: Weak connection to the standard's domain
25
+ 0-29: Appears misplaced; would fit better in a different layer
26
+
27
+ DOCUMENTATION SCORE \u2014 Is the description accurate, useful, and sufficient?
28
+ 90-100: Clear, accurate, implementation-agnostic, and complete
29
+ 70-89: Mostly good with minor gaps
30
+ 50-69: Generic or vague but not wrong
31
+ 30-49: Misleading or too brief to be useful
32
+ 0-29: Empty, missing, or actively wrong
33
+
34
+ PATTERN DETECTION \u2014 In addition to scoring, identify two structural anti-patterns. When found, apply the scoring impact below and include a specific remediation suggestion.
35
+
36
+ PATTERN A \u2014 Cross-layer reference annotation:
37
+ A node whose sole purpose is to carry metadata that belongs to another layer.
38
+ Indicators:
39
+ \u2022 Name uses x- prefix (e.g. x-database, x-ui, x-security, x-apm-*)
40
+ \u2022 Description says things like "links schema to...", "reference to ... in another layer",
41
+ "UI rendering hints", "security metadata", "database mapping information"
42
+ \u2022 Attributes describe properties of another layer's concepts, not this layer's
43
+ Scoring impact: Alignment score must be 0\u201329. This is a conceptual misalignment \u2014 the node
44
+ embeds cross-layer coupling inside a layer's type catalog instead of using relationships
45
+ or metadata attachments.
46
+ Required suggestion: Recommend moving this to a relationship property or cross-reference
47
+ annotation, and identify which layer it actually belongs to.
48
+
49
+ PATTERN B \u2014 Enum-masquerading node type:
50
+ A node that enumerates a closed set of values but is modeled as a first-class node type.
51
+ Indicators:
52
+ \u2022 Has only one attribute (commonly named "value" with type string or enum)
53
+ \u2022 Name or description uses words like "type", "kind", "mode", "status", or implies
54
+ a finite set of choices (e.g. "Core JSON data types", "String type definition")
55
+ \u2022 Represents a primitive value constraint rather than a structural concept
56
+ Scoring impact: Reduce alignment score by 20\u201330 points. These inflate the type catalog
57
+ and are modeling primitives incorrectly used.
58
+ Required suggestion: Recommend collapsing into an \`enum\`-constrained string attribute on
59
+ the parent schema (or a shared \`$defs\` enum referenced via \`$ref\`), and name the
60
+ specific attribute and schema where it should live.
61
+
62
+ Input node types:
63
+ \`\`\`json
64
+ ${JSON.stringify(inputItems, null, 2)}
65
+ \`\`\`
66
+
67
+ Return ONLY a JSON array (no prose, no markdown outside the array) with one object per node type:
68
+ [
69
+ {
70
+ "specNodeId": "string",
71
+ "alignmentScore": 0-100,
72
+ "alignmentReasoning": "brief explanation",
73
+ "documentationScore": 0-100,
74
+ "documentationReasoning": "brief explanation",
75
+ "suggestions": ["actionable suggestion 1", ...]
76
+ }
77
+ ]`;
78
+ }
79
+ /**
80
+ * Fallback standard names for layers without inspiredBy metadata.
81
+ * Public so NodeAIEvaluator can use the same mapping for LayerAIReview.standard.
82
+ */
83
+ getFallbackStandard(layerId) {
84
+ return {
85
+ motivation: "ArchiMate 3.2",
86
+ business: "ArchiMate 3.2",
87
+ security: "NIST SP 800-53",
88
+ application: "ArchiMate 3.2",
89
+ technology: "ArchiMate 3.2",
90
+ api: "OpenAPI 3.0",
91
+ "data-model": "JSON Schema Draft 7",
92
+ "data-store": "Database design patterns",
93
+ ux: "Component-based UI patterns",
94
+ navigation: "Application routing patterns",
95
+ apm: "OpenTelemetry",
96
+ testing: "Software testing best practices"
97
+ }[layerId] ?? "Architecture best practices";
98
+ }
99
+ }
100
+ export {
101
+ NodePromptTemplates
102
+ };
103
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/nodes/ai/prompts.ts"],
4
+ "sourcesContent": ["import type { LayerDefinition, ParsedNodeSchema } from \"../types.js\";\n\nexport class NodePromptTemplates {\n /**\n * Build a per-layer batch prompt that asks Claude to evaluate every node type\n * for alignment to the layer's inspiring standard and documentation quality.\n */\n layerEvaluation(context: {\n layerDef: LayerDefinition;\n schemas: ParsedNodeSchema[];\n }): string {\n const { layerDef, schemas } = context;\n const standard = layerDef.inspiredBy\n ? `${layerDef.inspiredBy.standard} ${layerDef.inspiredBy.version}`\n : this.getFallbackStandard(layerDef.id);\n\n const inputItems = schemas.map((s) => ({\n specNodeId: s.specNodeId,\n title: s.title,\n description: s.description,\n attributeNames: Object.keys(s.attributes.properties),\n }));\n\n return `You are evaluating node type definitions in a federated architecture specification.\n\nLayer: ${layerDef.name} (layer ${layerDef.number})\nInspiring Standard: ${standard}\n\nFor each node type, score it on two dimensions (0-100 each):\n\nALIGNMENT SCORE \u2014 How well does this node type conceptually belong in the ${layerDef.name} layer as defined by ${standard}?\n 90-100: Core concept in the standard, perfect fit for this layer\n 70-89: Clearly related to the standard, well-placed in this layer\n 50-69: Loosely related, could belong here or in an adjacent layer\n 30-49: Weak connection to the standard's domain\n 0-29: Appears misplaced; would fit better in a different layer\n\nDOCUMENTATION SCORE \u2014 Is the description accurate, useful, and sufficient?\n 90-100: Clear, accurate, implementation-agnostic, and complete\n 70-89: Mostly good with minor gaps\n 50-69: Generic or vague but not wrong\n 30-49: Misleading or too brief to be useful\n 0-29: Empty, missing, or actively wrong\n\nPATTERN DETECTION \u2014 In addition to scoring, identify two structural anti-patterns. When found, apply the scoring impact below and include a specific remediation suggestion.\n\nPATTERN A \u2014 Cross-layer reference annotation:\n A node whose sole purpose is to carry metadata that belongs to another layer.\n Indicators:\n \u2022 Name uses x- prefix (e.g. x-database, x-ui, x-security, x-apm-*)\n \u2022 Description says things like \"links schema to...\", \"reference to ... in another layer\",\n \"UI rendering hints\", \"security metadata\", \"database mapping information\"\n \u2022 Attributes describe properties of another layer's concepts, not this layer's\n Scoring impact: Alignment score must be 0\u201329. This is a conceptual misalignment \u2014 the node\n embeds cross-layer coupling inside a layer's type catalog instead of using relationships\n or metadata attachments.\n Required suggestion: Recommend moving this to a relationship property or cross-reference\n annotation, and identify which layer it actually belongs to.\n\nPATTERN B \u2014 Enum-masquerading node type:\n A node that enumerates a closed set of values but is modeled as a first-class node type.\n Indicators:\n \u2022 Has only one attribute (commonly named \"value\" with type string or enum)\n \u2022 Name or description uses words like \"type\", \"kind\", \"mode\", \"status\", or implies\n a finite set of choices (e.g. \"Core JSON data types\", \"String type definition\")\n \u2022 Represents a primitive value constraint rather than a structural concept\n Scoring impact: Reduce alignment score by 20\u201330 points. These inflate the type catalog\n and are modeling primitives incorrectly used.\n Required suggestion: Recommend collapsing into an \\`enum\\`-constrained string attribute on\n the parent schema (or a shared \\`$defs\\` enum referenced via \\`$ref\\`), and name the\n specific attribute and schema where it should live.\n\nInput node types:\n\\`\\`\\`json\n${JSON.stringify(inputItems, null, 2)}\n\\`\\`\\`\n\nReturn ONLY a JSON array (no prose, no markdown outside the array) with one object per node type:\n[\n {\n \"specNodeId\": \"string\",\n \"alignmentScore\": 0-100,\n \"alignmentReasoning\": \"brief explanation\",\n \"documentationScore\": 0-100,\n \"documentationReasoning\": \"brief explanation\",\n \"suggestions\": [\"actionable suggestion 1\", ...]\n }\n]`;\n }\n\n /**\n * Fallback standard names for layers without inspiredBy metadata.\n * Public so NodeAIEvaluator can use the same mapping for LayerAIReview.standard.\n */\n getFallbackStandard(layerId: string): string {\n const standards: Record<string, string> = {\n motivation: \"ArchiMate 3.2\",\n business: \"ArchiMate 3.2\",\n security: \"NIST SP 800-53\",\n application: \"ArchiMate 3.2\",\n technology: \"ArchiMate 3.2\",\n api: \"OpenAPI 3.0\",\n \"data-model\": \"JSON Schema Draft 7\",\n \"data-store\": \"Database design patterns\",\n ux: \"Component-based UI patterns\",\n navigation: \"Application routing patterns\",\n apm: \"OpenTelemetry\",\n testing: \"Software testing best practices\",\n };\n return standards[layerId] ?? \"Architecture best practices\";\n }\n}\n"],
5
+ "mappings": "AAEM,MAAO,oBAAmB;;;;;EAK9B,gBAAgB,SAGf;AACC,UAAM,EAAE,UAAU,QAAO,IAAK,SACxB,WAAW,SAAS,aACtB,GAAG,SAAS,WAAW,QAAQ,IAAI,SAAS,WAAW,OAAO,KAC9D,KAAK,oBAAoB,SAAS,EAAE,GAElC,aAAa,QAAQ,IAAI,CAAC,OAAO;MACrC,YAAY,EAAE;MACd,OAAO,EAAE;MACT,aAAa,EAAE;MACf,gBAAgB,OAAO,KAAK,EAAE,WAAW,UAAU;MACnD;AAEF,WAAO;;SAEF,SAAS,IAAI,WAAW,SAAS,MAAM;sBAC1B,QAAQ;;;;iFAI8C,SAAS,IAAI,wBAAwB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4CvH,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;;;;;;;;;;;;;;EAcnC;;;;;EAMA,oBAAoB,SAAe;AAejC,WAd0C;MACxC,YAAY;MACZ,UAAU;MACV,UAAU;MACV,aAAa;MACb,YAAY;MACZ,KAAK;MACL,cAAc;MACd,cAAc;MACd,IAAI;MACJ,YAAY;MACZ,KAAK;MACL,SAAS;MAEM,OAAO,KAAK;EAC/B;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ class NodeCompletenessChecker {
2
+ check(layerDefs, schemas) {
3
+ const issues = [], schemaIds = new Set(schemas.map((s) => s.specNodeId)), declaredIds = /* @__PURE__ */ new Set();
4
+ for (const layer of layerDefs)
5
+ for (const nodeType of layer.nodeTypes)
6
+ declaredIds.add(nodeType);
7
+ const layerById = new Map(layerDefs.map((l) => [l.id, l]));
8
+ for (const layer of layerDefs)
9
+ for (const nodeType of layer.nodeTypes)
10
+ schemaIds.has(nodeType) || issues.push({
11
+ layerId: layer.id,
12
+ specNodeId: nodeType,
13
+ issueType: "missing_schema",
14
+ detail: `"${nodeType}" is listed in ${layer.id} layer.json but has no corresponding .node.schema.json file.`
15
+ });
16
+ for (const schema of schemas)
17
+ if (!declaredIds.has(schema.specNodeId)) {
18
+ const layer = layerById.get(schema.layerId);
19
+ issues.push({
20
+ layerId: schema.layerId,
21
+ specNodeId: schema.specNodeId,
22
+ issueType: "orphaned_schema",
23
+ detail: `"${schema.specNodeId}" has a schema file but is not listed in ${layer ? layer.id : schema.layerId} layer.json.`
24
+ });
25
+ }
26
+ return issues;
27
+ }
28
+ }
29
+ export {
30
+ NodeCompletenessChecker
31
+ };
32
+ //# sourceMappingURL=node-completeness-checker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/audit/nodes/analysis/node-completeness-checker.ts"],
4
+ "sourcesContent": ["/**\n * Node schema completeness checker.\n * Pure function \u2014 no I/O.\n *\n * Compares layer.json node_types lists against actual schema files loaded from disk.\n */\n\nimport type { LayerDefinition, ParsedNodeSchema, SchemaCompletenessIssue } from \"../types.js\";\n\nexport class NodeCompletenessChecker {\n check(\n layerDefs: LayerDefinition[],\n schemas: ParsedNodeSchema[]\n ): SchemaCompletenessIssue[] {\n const issues: SchemaCompletenessIssue[] = [];\n\n // Build a set of all specNodeIds present as schema files\n const schemaIds = new Set(schemas.map((s) => s.specNodeId));\n\n // Build a set of all specNodeIds declared in layer.json files\n const declaredIds = new Set<string>();\n for (const layer of layerDefs) {\n for (const nodeType of layer.nodeTypes) {\n declaredIds.add(nodeType);\n }\n }\n\n // Build a quick lookup: layerId \u2192 layer definition\n const layerById = new Map(layerDefs.map((l) => [l.id, l]));\n\n // missing_schema: declared in layer.json but no schema file found\n for (const layer of layerDefs) {\n for (const nodeType of layer.nodeTypes) {\n if (!schemaIds.has(nodeType)) {\n issues.push({\n layerId: layer.id,\n specNodeId: nodeType,\n issueType: \"missing_schema\",\n detail: `\"${nodeType}\" is listed in ${layer.id} layer.json but has no corresponding .node.schema.json file.`,\n });\n }\n }\n }\n\n // orphaned_schema: schema file exists but not listed in any layer.json\n for (const schema of schemas) {\n if (!declaredIds.has(schema.specNodeId)) {\n const layer = layerById.get(schema.layerId);\n issues.push({\n layerId: schema.layerId,\n specNodeId: schema.specNodeId,\n issueType: \"orphaned_schema\",\n detail: `\"${schema.specNodeId}\" has a schema file but is not listed in ${layer ? layer.id : schema.layerId} layer.json.`,\n });\n }\n }\n\n return issues;\n }\n}\n"],
5
+ "mappings": "AASM,MAAO,wBAAuB;EAClC,MACE,WACA,SAA2B;AAE3B,UAAM,SAAoC,CAAA,GAGpC,YAAY,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,GAGpD,cAAc,oBAAI,IAAG;AAC3B,eAAW,SAAS;AAClB,iBAAW,YAAY,MAAM;AAC3B,oBAAY,IAAI,QAAQ;AAK5B,UAAM,YAAY,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAGzD,eAAW,SAAS;AAClB,iBAAW,YAAY,MAAM;AAC3B,QAAK,UAAU,IAAI,QAAQ,KACzB,OAAO,KAAK;UACV,SAAS,MAAM;UACf,YAAY;UACZ,WAAW;UACX,QAAQ,IAAI,QAAQ,kBAAkB,MAAM,EAAE;SAC/C;AAMP,eAAW,UAAU;AACnB,UAAI,CAAC,YAAY,IAAI,OAAO,UAAU,GAAG;AACvC,cAAM,QAAQ,UAAU,IAAI,OAAO,OAAO;AAC1C,eAAO,KAAK;UACV,SAAS,OAAO;UAChB,YAAY,OAAO;UACnB,WAAW;UACX,QAAQ,IAAI,OAAO,UAAU,4CAA4C,QAAQ,MAAM,KAAK,OAAO,OAAO;SAC3G;MACH;AAGF,WAAO;EACT;;",
6
+ "names": []
7
+ }
@@ -0,0 +1,47 @@
1
+ const GENERIC_DESCRIPTION_RE = /\w+ element in \w+ layer/i;
2
+ function classifyDescription(description) {
3
+ return !description || description.trim() === "" ? "empty" : GENERIC_DESCRIPTION_RE.test(description) ? "generic" : "good";
4
+ }
5
+ function countDocumentedAttributes(properties) {
6
+ return Object.values(properties).filter((p) => typeof p.description == "string" && p.description.trim() !== "").length;
7
+ }
8
+ class NodeDefinitionAnalyzer {
9
+ analyze(schema) {
10
+ const issues = [];
11
+ let score = 100;
12
+ const descriptionQuality = classifyDescription(schema.description), hasDescription = descriptionQuality !== "empty";
13
+ descriptionQuality === "empty" ? (issues.push({
14
+ severity: "error",
15
+ code: "EMPTY_DESCRIPTION",
16
+ message: `Node type "${schema.specNodeId}" has no description.`
17
+ }), score -= 30) : descriptionQuality === "generic" ? (issues.push({
18
+ severity: "warning",
19
+ code: "GENERIC_DESCRIPTION",
20
+ message: `Node type "${schema.specNodeId}" uses generic template description: "${schema.description}"`
21
+ }), score -= 15) : schema.description.trim().length < 20 && (issues.push({
22
+ severity: "info",
23
+ code: "SHORT_DESCRIPTION",
24
+ message: `Node type "${schema.specNodeId}" has a very short description (${schema.description.trim().length} chars).`
25
+ }), score -= 5);
26
+ const attributeCount = Object.keys(schema.attributes.properties).length, documentedAttributeCount = countDocumentedAttributes(schema.attributes.properties), attributeDocumentationRatio = attributeCount > 0 ? documentedAttributeCount / attributeCount : 1;
27
+ return attributeCount > 3 && attributeDocumentationRatio < 0.5 && (issues.push({
28
+ severity: "warning",
29
+ code: "LOW_ATTRIBUTE_DOCUMENTATION",
30
+ message: `Node type "${schema.specNodeId}" has low attribute documentation: ${documentedAttributeCount}/${attributeCount} attributes described.`
31
+ }), score -= 10), {
32
+ specNodeId: schema.specNodeId,
33
+ layerId: schema.layerId,
34
+ hasDescription,
35
+ descriptionQuality,
36
+ attributeCount,
37
+ documentedAttributeCount,
38
+ attributeDocumentationRatio,
39
+ issues,
40
+ score: Math.max(0, score)
41
+ };
42
+ }
43
+ }
44
+ export {
45
+ NodeDefinitionAnalyzer
46
+ };
47
+ //# sourceMappingURL=node-definition-analyzer.js.map