driftdetect-core 0.5.0 → 0.6.1

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 (350) hide show
  1. package/dist/boundaries/types.d.ts +1 -1
  2. package/dist/boundaries/types.d.ts.map +1 -1
  3. package/dist/call-graph/analysis/graph-builder.d.ts.map +1 -1
  4. package/dist/call-graph/analysis/graph-builder.js +1 -0
  5. package/dist/call-graph/analysis/graph-builder.js.map +1 -1
  6. package/dist/call-graph/extractors/go-data-access-extractor.d.ts +80 -0
  7. package/dist/call-graph/extractors/go-data-access-extractor.d.ts.map +1 -0
  8. package/dist/call-graph/extractors/go-data-access-extractor.js +457 -0
  9. package/dist/call-graph/extractors/go-data-access-extractor.js.map +1 -0
  10. package/dist/call-graph/extractors/go-extractor.d.ts +103 -0
  11. package/dist/call-graph/extractors/go-extractor.d.ts.map +1 -0
  12. package/dist/call-graph/extractors/go-extractor.js +509 -0
  13. package/dist/call-graph/extractors/go-extractor.js.map +1 -0
  14. package/dist/call-graph/extractors/go-hybrid-extractor.d.ts +97 -0
  15. package/dist/call-graph/extractors/go-hybrid-extractor.d.ts.map +1 -0
  16. package/dist/call-graph/extractors/go-hybrid-extractor.js +496 -0
  17. package/dist/call-graph/extractors/go-hybrid-extractor.js.map +1 -0
  18. package/dist/call-graph/extractors/regex/go-regex.d.ts +51 -0
  19. package/dist/call-graph/extractors/regex/go-regex.d.ts.map +1 -0
  20. package/dist/call-graph/extractors/regex/go-regex.js +435 -0
  21. package/dist/call-graph/extractors/regex/go-regex.js.map +1 -0
  22. package/dist/call-graph/extractors/regex/index.d.ts +1 -0
  23. package/dist/call-graph/extractors/regex/index.d.ts.map +1 -1
  24. package/dist/call-graph/extractors/regex/index.js +8 -0
  25. package/dist/call-graph/extractors/regex/index.js.map +1 -1
  26. package/dist/call-graph/index.d.ts +3 -0
  27. package/dist/call-graph/index.d.ts.map +1 -1
  28. package/dist/call-graph/index.js +5 -0
  29. package/dist/call-graph/index.js.map +1 -1
  30. package/dist/call-graph/types.d.ts +1 -1
  31. package/dist/call-graph/types.d.ts.map +1 -1
  32. package/dist/constraints/extraction/constraint-synthesizer.d.ts +72 -0
  33. package/dist/constraints/extraction/constraint-synthesizer.d.ts.map +1 -0
  34. package/dist/constraints/extraction/constraint-synthesizer.js +336 -0
  35. package/dist/constraints/extraction/constraint-synthesizer.js.map +1 -0
  36. package/dist/constraints/extraction/index.d.ts +10 -0
  37. package/dist/constraints/extraction/index.d.ts.map +1 -0
  38. package/dist/constraints/extraction/index.js +10 -0
  39. package/dist/constraints/extraction/index.js.map +1 -0
  40. package/dist/constraints/extraction/invariant-detector.d.ts +109 -0
  41. package/dist/constraints/extraction/invariant-detector.d.ts.map +1 -0
  42. package/dist/constraints/extraction/invariant-detector.js +979 -0
  43. package/dist/constraints/extraction/invariant-detector.js.map +1 -0
  44. package/dist/constraints/index.d.ts +15 -0
  45. package/dist/constraints/index.d.ts.map +1 -0
  46. package/dist/constraints/index.js +16 -0
  47. package/dist/constraints/index.js.map +1 -0
  48. package/dist/constraints/store/constraint-store.d.ts +110 -0
  49. package/dist/constraints/store/constraint-store.d.ts.map +1 -0
  50. package/dist/constraints/store/constraint-store.js +584 -0
  51. package/dist/constraints/store/constraint-store.js.map +1 -0
  52. package/dist/constraints/types.d.ts +605 -0
  53. package/dist/constraints/types.d.ts.map +1 -0
  54. package/dist/constraints/types.js +57 -0
  55. package/dist/constraints/types.js.map +1 -0
  56. package/dist/constraints/verification/constraint-verifier.d.ts +100 -0
  57. package/dist/constraints/verification/constraint-verifier.d.ts.map +1 -0
  58. package/dist/constraints/verification/constraint-verifier.js +638 -0
  59. package/dist/constraints/verification/constraint-verifier.js.map +1 -0
  60. package/dist/constraints/verification/index.d.ts +8 -0
  61. package/dist/constraints/verification/index.d.ts.map +1 -0
  62. package/dist/constraints/verification/index.js +8 -0
  63. package/dist/constraints/verification/index.js.map +1 -0
  64. package/dist/decisions/analyzer/decision-mining-analyzer.d.ts +121 -0
  65. package/dist/decisions/analyzer/decision-mining-analyzer.d.ts.map +1 -0
  66. package/dist/decisions/analyzer/decision-mining-analyzer.js +904 -0
  67. package/dist/decisions/analyzer/decision-mining-analyzer.js.map +1 -0
  68. package/dist/decisions/analyzer/index.d.ts +5 -0
  69. package/dist/decisions/analyzer/index.d.ts.map +1 -0
  70. package/dist/decisions/analyzer/index.js +5 -0
  71. package/dist/decisions/analyzer/index.js.map +1 -0
  72. package/dist/decisions/extractors/base-commit-extractor.d.ts +104 -0
  73. package/dist/decisions/extractors/base-commit-extractor.d.ts.map +1 -0
  74. package/dist/decisions/extractors/base-commit-extractor.js +305 -0
  75. package/dist/decisions/extractors/base-commit-extractor.js.map +1 -0
  76. package/dist/decisions/extractors/csharp-commit-extractor.d.ts +18 -0
  77. package/dist/decisions/extractors/csharp-commit-extractor.d.ts.map +1 -0
  78. package/dist/decisions/extractors/csharp-commit-extractor.js +281 -0
  79. package/dist/decisions/extractors/csharp-commit-extractor.js.map +1 -0
  80. package/dist/decisions/extractors/index.d.ts +31 -0
  81. package/dist/decisions/extractors/index.d.ts.map +1 -0
  82. package/dist/decisions/extractors/index.js +63 -0
  83. package/dist/decisions/extractors/index.js.map +1 -0
  84. package/dist/decisions/extractors/java-commit-extractor.d.ts +18 -0
  85. package/dist/decisions/extractors/java-commit-extractor.d.ts.map +1 -0
  86. package/dist/decisions/extractors/java-commit-extractor.js +248 -0
  87. package/dist/decisions/extractors/java-commit-extractor.js.map +1 -0
  88. package/dist/decisions/extractors/php-commit-extractor.d.ts +18 -0
  89. package/dist/decisions/extractors/php-commit-extractor.d.ts.map +1 -0
  90. package/dist/decisions/extractors/php-commit-extractor.js +280 -0
  91. package/dist/decisions/extractors/php-commit-extractor.js.map +1 -0
  92. package/dist/decisions/extractors/python-commit-extractor.d.ts +18 -0
  93. package/dist/decisions/extractors/python-commit-extractor.d.ts.map +1 -0
  94. package/dist/decisions/extractors/python-commit-extractor.js +248 -0
  95. package/dist/decisions/extractors/python-commit-extractor.js.map +1 -0
  96. package/dist/decisions/extractors/typescript-commit-extractor.d.ts +37 -0
  97. package/dist/decisions/extractors/typescript-commit-extractor.d.ts.map +1 -0
  98. package/dist/decisions/extractors/typescript-commit-extractor.js +229 -0
  99. package/dist/decisions/extractors/typescript-commit-extractor.js.map +1 -0
  100. package/dist/decisions/git/commit-parser.d.ts +58 -0
  101. package/dist/decisions/git/commit-parser.d.ts.map +1 -0
  102. package/dist/decisions/git/commit-parser.js +344 -0
  103. package/dist/decisions/git/commit-parser.js.map +1 -0
  104. package/dist/decisions/git/diff-analyzer.d.ts +30 -0
  105. package/dist/decisions/git/diff-analyzer.d.ts.map +1 -0
  106. package/dist/decisions/git/diff-analyzer.js +492 -0
  107. package/dist/decisions/git/diff-analyzer.js.map +1 -0
  108. package/dist/decisions/git/git-walker.d.ts +64 -0
  109. package/dist/decisions/git/git-walker.d.ts.map +1 -0
  110. package/dist/decisions/git/git-walker.js +441 -0
  111. package/dist/decisions/git/git-walker.js.map +1 -0
  112. package/dist/decisions/git/index.d.ts +11 -0
  113. package/dist/decisions/git/index.d.ts.map +1 -0
  114. package/dist/decisions/git/index.js +13 -0
  115. package/dist/decisions/git/index.js.map +1 -0
  116. package/dist/decisions/git/types.d.ts +223 -0
  117. package/dist/decisions/git/types.d.ts.map +1 -0
  118. package/dist/decisions/git/types.js +7 -0
  119. package/dist/decisions/git/types.js.map +1 -0
  120. package/dist/decisions/index.d.ts +27 -0
  121. package/dist/decisions/index.d.ts.map +1 -0
  122. package/dist/decisions/index.js +45 -0
  123. package/dist/decisions/index.js.map +1 -0
  124. package/dist/decisions/types.d.ts +530 -0
  125. package/dist/decisions/types.d.ts.map +1 -0
  126. package/dist/decisions/types.js +8 -0
  127. package/dist/decisions/types.js.map +1 -0
  128. package/dist/go/go-analyzer.d.ts +203 -0
  129. package/dist/go/go-analyzer.d.ts.map +1 -0
  130. package/dist/go/go-analyzer.js +509 -0
  131. package/dist/go/go-analyzer.js.map +1 -0
  132. package/dist/go/index.d.ts +7 -0
  133. package/dist/go/index.d.ts.map +1 -0
  134. package/dist/go/index.js +8 -0
  135. package/dist/go/index.js.map +1 -0
  136. package/dist/index.d.ts +11 -0
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +56 -0
  139. package/dist/index.js.map +1 -1
  140. package/dist/parsers/tree-sitter/go-loader.d.ts +50 -0
  141. package/dist/parsers/tree-sitter/go-loader.d.ts.map +1 -0
  142. package/dist/parsers/tree-sitter/go-loader.js +161 -0
  143. package/dist/parsers/tree-sitter/go-loader.js.map +1 -0
  144. package/dist/parsers/tree-sitter/tree-sitter-go-parser.d.ts +250 -0
  145. package/dist/parsers/tree-sitter/tree-sitter-go-parser.d.ts.map +1 -0
  146. package/dist/parsers/tree-sitter/tree-sitter-go-parser.js +707 -0
  147. package/dist/parsers/tree-sitter/tree-sitter-go-parser.js.map +1 -0
  148. package/dist/parsers/types.d.ts +1 -1
  149. package/dist/parsers/types.d.ts.map +1 -1
  150. package/dist/simulation/approach-generator.d.ts +73 -0
  151. package/dist/simulation/approach-generator.d.ts.map +1 -0
  152. package/dist/simulation/approach-generator.js +371 -0
  153. package/dist/simulation/approach-generator.js.map +1 -0
  154. package/dist/simulation/index.d.ts +14 -0
  155. package/dist/simulation/index.d.ts.map +1 -0
  156. package/dist/simulation/index.js +19 -0
  157. package/dist/simulation/index.js.map +1 -0
  158. package/dist/simulation/language-strategies/csharp-strategies.d.ts +17 -0
  159. package/dist/simulation/language-strategies/csharp-strategies.d.ts.map +1 -0
  160. package/dist/simulation/language-strategies/csharp-strategies.js +118 -0
  161. package/dist/simulation/language-strategies/csharp-strategies.js.map +1 -0
  162. package/dist/simulation/language-strategies/index.d.ts +41 -0
  163. package/dist/simulation/language-strategies/index.d.ts.map +1 -0
  164. package/dist/simulation/language-strategies/index.js +92 -0
  165. package/dist/simulation/language-strategies/index.js.map +1 -0
  166. package/dist/simulation/language-strategies/java-strategies.d.ts +17 -0
  167. package/dist/simulation/language-strategies/java-strategies.d.ts.map +1 -0
  168. package/dist/simulation/language-strategies/java-strategies.js +119 -0
  169. package/dist/simulation/language-strategies/java-strategies.js.map +1 -0
  170. package/dist/simulation/language-strategies/php-strategies.d.ts +17 -0
  171. package/dist/simulation/language-strategies/php-strategies.d.ts.map +1 -0
  172. package/dist/simulation/language-strategies/php-strategies.js +129 -0
  173. package/dist/simulation/language-strategies/php-strategies.js.map +1 -0
  174. package/dist/simulation/language-strategies/python-strategies.d.ts +17 -0
  175. package/dist/simulation/language-strategies/python-strategies.d.ts.map +1 -0
  176. package/dist/simulation/language-strategies/python-strategies.js +208 -0
  177. package/dist/simulation/language-strategies/python-strategies.js.map +1 -0
  178. package/dist/simulation/language-strategies/types.d.ts +67 -0
  179. package/dist/simulation/language-strategies/types.d.ts.map +1 -0
  180. package/dist/simulation/language-strategies/types.js +23 -0
  181. package/dist/simulation/language-strategies/types.js.map +1 -0
  182. package/dist/simulation/language-strategies/typescript-strategies.d.ts +17 -0
  183. package/dist/simulation/language-strategies/typescript-strategies.d.ts.map +1 -0
  184. package/dist/simulation/language-strategies/typescript-strategies.js +251 -0
  185. package/dist/simulation/language-strategies/typescript-strategies.js.map +1 -0
  186. package/dist/simulation/scorers/friction-scorer.d.ts +45 -0
  187. package/dist/simulation/scorers/friction-scorer.d.ts.map +1 -0
  188. package/dist/simulation/scorers/friction-scorer.js +336 -0
  189. package/dist/simulation/scorers/friction-scorer.js.map +1 -0
  190. package/dist/simulation/scorers/impact-scorer.d.ts +56 -0
  191. package/dist/simulation/scorers/impact-scorer.d.ts.map +1 -0
  192. package/dist/simulation/scorers/impact-scorer.js +273 -0
  193. package/dist/simulation/scorers/impact-scorer.js.map +1 -0
  194. package/dist/simulation/scorers/index.d.ts +12 -0
  195. package/dist/simulation/scorers/index.d.ts.map +1 -0
  196. package/dist/simulation/scorers/index.js +12 -0
  197. package/dist/simulation/scorers/index.js.map +1 -0
  198. package/dist/simulation/scorers/pattern-alignment-scorer.d.ts +83 -0
  199. package/dist/simulation/scorers/pattern-alignment-scorer.d.ts.map +1 -0
  200. package/dist/simulation/scorers/pattern-alignment-scorer.js +367 -0
  201. package/dist/simulation/scorers/pattern-alignment-scorer.js.map +1 -0
  202. package/dist/simulation/scorers/security-scorer.d.ts +63 -0
  203. package/dist/simulation/scorers/security-scorer.d.ts.map +1 -0
  204. package/dist/simulation/scorers/security-scorer.js +346 -0
  205. package/dist/simulation/scorers/security-scorer.js.map +1 -0
  206. package/dist/simulation/simulation-engine.d.ts +89 -0
  207. package/dist/simulation/simulation-engine.d.ts.map +1 -0
  208. package/dist/simulation/simulation-engine.js +480 -0
  209. package/dist/simulation/simulation-engine.js.map +1 -0
  210. package/dist/simulation/types.d.ts +200 -0
  211. package/dist/simulation/types.d.ts.map +1 -0
  212. package/dist/simulation/types.js +23 -0
  213. package/dist/simulation/types.js.map +1 -0
  214. package/dist/speculative/approach-generator.d.ts +2 -0
  215. package/dist/speculative/approach-generator.d.ts.map +1 -0
  216. package/dist/speculative/approach-generator.js +2 -0
  217. package/dist/speculative/approach-generator.js.map +1 -0
  218. package/dist/speculative/templates/types.d.ts +133 -0
  219. package/dist/speculative/templates/types.d.ts.map +1 -0
  220. package/dist/speculative/templates/types.js +208 -0
  221. package/dist/speculative/templates/types.js.map +1 -0
  222. package/dist/speculative/types.d.ts +523 -0
  223. package/dist/speculative/types.d.ts.map +1 -0
  224. package/dist/speculative/types.js +71 -0
  225. package/dist/speculative/types.js.map +1 -0
  226. package/dist/test-topology/extractors/base-test-extractor.d.ts +1 -1
  227. package/dist/test-topology/extractors/base-test-extractor.d.ts.map +1 -1
  228. package/dist/test-topology/extractors/base-test-extractor.js.map +1 -1
  229. package/dist/test-topology/extractors/go-test-extractor.d.ts +33 -0
  230. package/dist/test-topology/extractors/go-test-extractor.d.ts.map +1 -0
  231. package/dist/test-topology/extractors/go-test-extractor.js +436 -0
  232. package/dist/test-topology/extractors/go-test-extractor.js.map +1 -0
  233. package/dist/test-topology/extractors/index.d.ts +1 -0
  234. package/dist/test-topology/extractors/index.d.ts.map +1 -1
  235. package/dist/test-topology/extractors/index.js +1 -0
  236. package/dist/test-topology/extractors/index.js.map +1 -1
  237. package/dist/test-topology/extractors/regex/go-test-regex.d.ts +62 -0
  238. package/dist/test-topology/extractors/regex/go-test-regex.d.ts.map +1 -0
  239. package/dist/test-topology/extractors/regex/go-test-regex.js +528 -0
  240. package/dist/test-topology/extractors/regex/go-test-regex.js.map +1 -0
  241. package/dist/test-topology/extractors/regex/index.d.ts +1 -0
  242. package/dist/test-topology/extractors/regex/index.d.ts.map +1 -1
  243. package/dist/test-topology/extractors/regex/index.js +4 -0
  244. package/dist/test-topology/extractors/regex/index.js.map +1 -1
  245. package/dist/test-topology/hybrid-test-topology-analyzer.d.ts.map +1 -1
  246. package/dist/test-topology/hybrid-test-topology-analyzer.js +1 -0
  247. package/dist/test-topology/hybrid-test-topology-analyzer.js.map +1 -1
  248. package/dist/test-topology/test-topology-analyzer.d.ts.map +1 -1
  249. package/dist/test-topology/test-topology-analyzer.js +1 -0
  250. package/dist/test-topology/test-topology-analyzer.js.map +1 -1
  251. package/dist/test-topology/types.d.ts +2 -2
  252. package/dist/test-topology/types.d.ts.map +1 -1
  253. package/dist/unified-provider/matching/database-sql-matcher.d.ts +42 -0
  254. package/dist/unified-provider/matching/database-sql-matcher.d.ts.map +1 -0
  255. package/dist/unified-provider/matching/database-sql-matcher.js +282 -0
  256. package/dist/unified-provider/matching/database-sql-matcher.js.map +1 -0
  257. package/dist/unified-provider/matching/gorm-matcher.d.ts +41 -0
  258. package/dist/unified-provider/matching/gorm-matcher.d.ts.map +1 -0
  259. package/dist/unified-provider/matching/gorm-matcher.js +222 -0
  260. package/dist/unified-provider/matching/gorm-matcher.js.map +1 -0
  261. package/dist/unified-provider/matching/index.d.ts +3 -0
  262. package/dist/unified-provider/matching/index.d.ts.map +1 -1
  263. package/dist/unified-provider/matching/index.js +4 -0
  264. package/dist/unified-provider/matching/index.js.map +1 -1
  265. package/dist/unified-provider/matching/matcher-registry.d.ts.map +1 -1
  266. package/dist/unified-provider/matching/matcher-registry.js +7 -0
  267. package/dist/unified-provider/matching/matcher-registry.js.map +1 -1
  268. package/dist/unified-provider/matching/sqlx-matcher.d.ts +40 -0
  269. package/dist/unified-provider/matching/sqlx-matcher.d.ts.map +1 -0
  270. package/dist/unified-provider/matching/sqlx-matcher.js +214 -0
  271. package/dist/unified-provider/matching/sqlx-matcher.js.map +1 -0
  272. package/dist/unified-provider/normalization/go-normalizer.d.ts +62 -0
  273. package/dist/unified-provider/normalization/go-normalizer.d.ts.map +1 -0
  274. package/dist/unified-provider/normalization/go-normalizer.js +608 -0
  275. package/dist/unified-provider/normalization/go-normalizer.js.map +1 -0
  276. package/dist/unified-provider/normalization/index.d.ts +1 -0
  277. package/dist/unified-provider/normalization/index.d.ts.map +1 -1
  278. package/dist/unified-provider/normalization/index.js +6 -1
  279. package/dist/unified-provider/normalization/index.js.map +1 -1
  280. package/dist/unified-provider/types.d.ts +1 -1
  281. package/dist/unified-provider/types.d.ts.map +1 -1
  282. package/dist/wpf/extractors/binding-error-detector.d.ts +75 -0
  283. package/dist/wpf/extractors/binding-error-detector.d.ts.map +1 -0
  284. package/dist/wpf/extractors/binding-error-detector.js +290 -0
  285. package/dist/wpf/extractors/binding-error-detector.js.map +1 -0
  286. package/dist/wpf/extractors/code-behind-linker.d.ts +70 -0
  287. package/dist/wpf/extractors/code-behind-linker.d.ts.map +1 -0
  288. package/dist/wpf/extractors/code-behind-linker.js +172 -0
  289. package/dist/wpf/extractors/code-behind-linker.js.map +1 -0
  290. package/dist/wpf/extractors/dependency-property-extractor.d.ts +61 -0
  291. package/dist/wpf/extractors/dependency-property-extractor.d.ts.map +1 -0
  292. package/dist/wpf/extractors/dependency-property-extractor.js +201 -0
  293. package/dist/wpf/extractors/dependency-property-extractor.js.map +1 -0
  294. package/dist/wpf/extractors/regex/viewmodel-regex.d.ts +82 -0
  295. package/dist/wpf/extractors/regex/viewmodel-regex.d.ts.map +1 -0
  296. package/dist/wpf/extractors/regex/viewmodel-regex.js +412 -0
  297. package/dist/wpf/extractors/regex/viewmodel-regex.js.map +1 -0
  298. package/dist/wpf/extractors/regex/xaml-regex.d.ts +77 -0
  299. package/dist/wpf/extractors/regex/xaml-regex.d.ts.map +1 -0
  300. package/dist/wpf/extractors/regex/xaml-regex.js +353 -0
  301. package/dist/wpf/extractors/regex/xaml-regex.js.map +1 -0
  302. package/dist/wpf/extractors/resource-dictionary-parser.d.ts +103 -0
  303. package/dist/wpf/extractors/resource-dictionary-parser.d.ts.map +1 -0
  304. package/dist/wpf/extractors/resource-dictionary-parser.js +296 -0
  305. package/dist/wpf/extractors/resource-dictionary-parser.js.map +1 -0
  306. package/dist/wpf/extractors/value-converter-extractor.d.ts +128 -0
  307. package/dist/wpf/extractors/value-converter-extractor.d.ts.map +1 -0
  308. package/dist/wpf/extractors/value-converter-extractor.js +312 -0
  309. package/dist/wpf/extractors/value-converter-extractor.js.map +1 -0
  310. package/dist/wpf/extractors/viewmodel-hybrid-extractor.d.ts +104 -0
  311. package/dist/wpf/extractors/viewmodel-hybrid-extractor.d.ts.map +1 -0
  312. package/dist/wpf/extractors/viewmodel-hybrid-extractor.js +513 -0
  313. package/dist/wpf/extractors/viewmodel-hybrid-extractor.js.map +1 -0
  314. package/dist/wpf/extractors/xaml-hybrid-extractor.d.ts +98 -0
  315. package/dist/wpf/extractors/xaml-hybrid-extractor.d.ts.map +1 -0
  316. package/dist/wpf/extractors/xaml-hybrid-extractor.js +444 -0
  317. package/dist/wpf/extractors/xaml-hybrid-extractor.js.map +1 -0
  318. package/dist/wpf/index.d.ts +25 -0
  319. package/dist/wpf/index.d.ts.map +1 -0
  320. package/dist/wpf/index.js +31 -0
  321. package/dist/wpf/index.js.map +1 -0
  322. package/dist/wpf/integration/wpf-callgraph-adapter.d.ts +82 -0
  323. package/dist/wpf/integration/wpf-callgraph-adapter.d.ts.map +1 -0
  324. package/dist/wpf/integration/wpf-callgraph-adapter.js +311 -0
  325. package/dist/wpf/integration/wpf-callgraph-adapter.js.map +1 -0
  326. package/dist/wpf/integration/wpf-data-flow-tracer.d.ts +129 -0
  327. package/dist/wpf/integration/wpf-data-flow-tracer.d.ts.map +1 -0
  328. package/dist/wpf/integration/wpf-data-flow-tracer.js +367 -0
  329. package/dist/wpf/integration/wpf-data-flow-tracer.js.map +1 -0
  330. package/dist/wpf/linkers/datacontext-resolver.d.ts +66 -0
  331. package/dist/wpf/linkers/datacontext-resolver.d.ts.map +1 -0
  332. package/dist/wpf/linkers/datacontext-resolver.js +240 -0
  333. package/dist/wpf/linkers/datacontext-resolver.js.map +1 -0
  334. package/dist/wpf/linkers/viewmodel-linker.d.ts +71 -0
  335. package/dist/wpf/linkers/viewmodel-linker.d.ts.map +1 -0
  336. package/dist/wpf/linkers/viewmodel-linker.js +268 -0
  337. package/dist/wpf/linkers/viewmodel-linker.js.map +1 -0
  338. package/dist/wpf/types.d.ts +451 -0
  339. package/dist/wpf/types.d.ts.map +1 -0
  340. package/dist/wpf/types.js +8 -0
  341. package/dist/wpf/types.js.map +1 -0
  342. package/dist/wpf/wpf-analyzer.d.ts +114 -0
  343. package/dist/wpf/wpf-analyzer.d.ts.map +1 -0
  344. package/dist/wpf/wpf-analyzer.js +332 -0
  345. package/dist/wpf/wpf-analyzer.js.map +1 -0
  346. package/dist/wrappers/integration/adapter.d.ts.map +1 -1
  347. package/dist/wrappers/integration/adapter.js +1 -0
  348. package/dist/wrappers/integration/adapter.js.map +1 -1
  349. package/package.json +29 -18
  350. package/LICENSE +0 -21
@@ -0,0 +1,979 @@
1
+ /**
2
+ * Invariant Detector
3
+ *
4
+ * Analyzes Drift's existing data (patterns, call graphs, boundaries, test topology,
5
+ * error handling) to discover architectural invariants that can become constraints.
6
+ *
7
+ * This is the semantic analysis layer that mines invariants from:
8
+ * - Pattern data (high-confidence approved patterns)
9
+ * - Call graph (auth-before-data-access, validation patterns)
10
+ * - Boundaries (data access layer invariants)
11
+ * - Test topology (coverage requirements)
12
+ * - Error handling (error boundary patterns)
13
+ */
14
+ // =============================================================================
15
+ // Invariant Detector
16
+ // =============================================================================
17
+ export class InvariantDetector {
18
+ config;
19
+ constructor(config) {
20
+ this.config = config;
21
+ }
22
+ /**
23
+ * Detect invariants from all available Drift data
24
+ */
25
+ async detectAll(options = {}) {
26
+ const invariants = [];
27
+ const categories = options.categories ?? [
28
+ 'api', 'auth', 'data', 'error', 'test', 'security', 'structural'
29
+ ];
30
+ // Detect from patterns
31
+ if (this.config.patternStore) {
32
+ const patternInvariants = await this.detectFromPatterns(categories, options);
33
+ invariants.push(...patternInvariants);
34
+ }
35
+ // Detect from call graph
36
+ if (this.config.callGraphStore) {
37
+ const callGraphInvariants = await this.detectFromCallGraph(options);
38
+ invariants.push(...callGraphInvariants);
39
+ }
40
+ // Detect from boundaries
41
+ if (this.config.boundaryStore) {
42
+ const boundaryInvariants = await this.detectFromBoundaries(options);
43
+ invariants.push(...boundaryInvariants);
44
+ }
45
+ // Detect from test topology
46
+ if (this.config.testTopologyAnalyzer) {
47
+ const testInvariants = await this.detectFromTestTopology(options);
48
+ invariants.push(...testInvariants);
49
+ }
50
+ // Detect from error handling
51
+ if (this.config.errorHandlingAnalyzer) {
52
+ const errorInvariants = await this.detectFromErrorHandling(options);
53
+ invariants.push(...errorInvariants);
54
+ }
55
+ // Filter by confidence threshold
56
+ const minConfidence = options.minConfidence ?? 0.90;
57
+ return invariants.filter(inv => inv.constraint.confidence.score >= minConfidence);
58
+ }
59
+ // ===========================================================================
60
+ // Pattern-Based Detection
61
+ // ===========================================================================
62
+ /**
63
+ * Detect invariants from pattern data
64
+ */
65
+ async detectFromPatterns(categories, options) {
66
+ const invariants = [];
67
+ const store = this.config.patternStore;
68
+ // Get all approved patterns with high confidence
69
+ const patterns = store.getAll().filter(p => p.status === 'approved' &&
70
+ p.confidence.score >= 0.85 &&
71
+ categories.includes(p.category));
72
+ for (const pattern of patterns) {
73
+ const detected = this.patternToInvariant(pattern, options);
74
+ if (detected) {
75
+ invariants.push(detected);
76
+ }
77
+ }
78
+ return invariants;
79
+ }
80
+ /**
81
+ * Convert a high-confidence pattern to an invariant
82
+ */
83
+ patternToInvariant(pattern, options) {
84
+ // Only convert patterns with enough evidence
85
+ if (pattern.locations.length < 3)
86
+ return null;
87
+ const category = pattern.category;
88
+ const language = this.detectLanguageFromPattern(pattern);
89
+ // Build predicate based on pattern type
90
+ const predicate = this.buildPredicateFromPattern(pattern);
91
+ // Calculate confidence
92
+ const violations = pattern.outliers ?? [];
93
+ const conforming = pattern.locations.length;
94
+ const violating = violations.length;
95
+ const confidence = conforming / (conforming + violating);
96
+ // Build violation details
97
+ const violationDetails = violations.map((o) => ({
98
+ file: o.file,
99
+ line: o.line,
100
+ reason: o.reason ?? 'Outlier from pattern',
101
+ }));
102
+ // Build confidence object conditionally to satisfy exactOptionalPropertyTypes
103
+ const constraintConfidence = {
104
+ score: confidence,
105
+ evidence: conforming,
106
+ violations: violating,
107
+ lastVerified: new Date().toISOString(),
108
+ };
109
+ if (options.includeViolationDetails && violationDetails.length > 0) {
110
+ constraintConfidence.violationDetails = violationDetails;
111
+ }
112
+ return {
113
+ constraint: {
114
+ name: `${pattern.name} Invariant`,
115
+ description: `All ${pattern.name} instances must follow the established pattern`,
116
+ category,
117
+ derivedFrom: {
118
+ patterns: [pattern.id],
119
+ callGraphPaths: [],
120
+ boundaries: [],
121
+ },
122
+ invariant: {
123
+ type: this.inferConstraintType(pattern),
124
+ condition: pattern.description ?? `Must follow ${pattern.name} pattern`,
125
+ predicate,
126
+ },
127
+ scope: this.buildScopeFromPattern(pattern),
128
+ confidence: constraintConfidence,
129
+ enforcement: {
130
+ level: confidence >= 0.95 ? 'error' : 'warning',
131
+ guidance: `Follow the ${pattern.name} pattern as established in the codebase`,
132
+ },
133
+ status: 'discovered',
134
+ language,
135
+ },
136
+ evidence: {
137
+ conforming,
138
+ violating,
139
+ conformingLocations: pattern.locations.slice(0, 5).map((l) => `${l.file}:${l.line}`),
140
+ violatingLocations: violations.slice(0, 5).map((o) => `${o.file}:${o.line}`),
141
+ sources: [`pattern:${pattern.id}`],
142
+ },
143
+ violations: violationDetails,
144
+ };
145
+ }
146
+ // ===========================================================================
147
+ // Call Graph-Based Detection
148
+ // ===========================================================================
149
+ /**
150
+ * Detect invariants from call graph analysis
151
+ */
152
+ async detectFromCallGraph(_options) {
153
+ const invariants = [];
154
+ const store = this.config.callGraphStore;
155
+ // Load call graph
156
+ const graph = await store.load();
157
+ if (!graph)
158
+ return invariants;
159
+ // Detect auth-before-data-access invariants
160
+ const authInvariants = this.detectAuthBeforeDataAccess(graph);
161
+ invariants.push(...authInvariants);
162
+ // Detect validation patterns
163
+ const validationInvariants = this.detectValidationPatterns(graph);
164
+ invariants.push(...validationInvariants);
165
+ return invariants;
166
+ }
167
+ /**
168
+ * Detect auth-before-data-access patterns
169
+ */
170
+ detectAuthBeforeDataAccess(graph) {
171
+ const invariants = [];
172
+ // Find entry points that access data
173
+ const entryPointIds = graph.entryPoints ?? [];
174
+ const entryPointsWithData = [];
175
+ for (const id of entryPointIds) {
176
+ const func = graph.functions.get(id);
177
+ if (func && func.dataAccess && func.dataAccess.length > 0) {
178
+ entryPointsWithData.push(func);
179
+ }
180
+ }
181
+ if (entryPointsWithData.length < 3)
182
+ return invariants;
183
+ // Group by whether they have auth in the call chain
184
+ const withAuth = [];
185
+ const withoutAuth = [];
186
+ for (const entry of entryPointsWithData) {
187
+ const hasAuth = this.hasAuthInCallChain(entry, graph);
188
+ if (hasAuth) {
189
+ withAuth.push(entry);
190
+ }
191
+ else {
192
+ withoutAuth.push(entry);
193
+ }
194
+ }
195
+ // If most entry points have auth, create an invariant
196
+ const total = withAuth.length + withoutAuth.length;
197
+ if (total >= 3 && withAuth.length / total >= 0.8) {
198
+ const confidence = withAuth.length / total;
199
+ invariants.push({
200
+ constraint: {
201
+ name: 'Auth Before Data Access',
202
+ description: 'Entry points that access data must have authentication in the call chain',
203
+ category: 'auth',
204
+ derivedFrom: {
205
+ patterns: [],
206
+ callGraphPaths: entryPointsWithData.map(e => e.id),
207
+ boundaries: [],
208
+ },
209
+ invariant: {
210
+ type: 'must_precede',
211
+ condition: 'Authentication must occur before data access',
212
+ predicate: {
213
+ callChain: {
214
+ from: 'entryPoint',
215
+ to: 'dataAccess',
216
+ mustInclude: ['authenticate', 'authorize', 'checkAuth', 'requireAuth'],
217
+ },
218
+ },
219
+ },
220
+ scope: {
221
+ entryPoints: true,
222
+ dataAccessors: true,
223
+ },
224
+ confidence: {
225
+ score: confidence,
226
+ evidence: withAuth.length,
227
+ violations: withoutAuth.length,
228
+ lastVerified: new Date().toISOString(),
229
+ },
230
+ enforcement: {
231
+ level: 'error',
232
+ guidance: 'Add authentication middleware or check before accessing data',
233
+ },
234
+ status: 'discovered',
235
+ language: 'all',
236
+ },
237
+ evidence: {
238
+ conforming: withAuth.length,
239
+ violating: withoutAuth.length,
240
+ conformingLocations: withAuth.slice(0, 5).map(f => `${f.file}:${f.startLine}`),
241
+ violatingLocations: withoutAuth.slice(0, 5).map(f => `${f.file}:${f.startLine}`),
242
+ sources: ['callGraph'],
243
+ },
244
+ violations: withoutAuth.map(f => ({
245
+ file: f.file,
246
+ line: f.startLine,
247
+ reason: 'Entry point accesses data without authentication in call chain',
248
+ })),
249
+ });
250
+ }
251
+ return invariants;
252
+ }
253
+ /**
254
+ * Check if a function has auth in its call chain
255
+ */
256
+ hasAuthInCallChain(func, graph) {
257
+ const authPatterns = [
258
+ /auth/i, /authenticate/i, /authorize/i, /checkAuth/i,
259
+ /requireAuth/i, /isAuthenticated/i, /verifyToken/i,
260
+ /validateToken/i, /checkPermission/i, /hasRole/i,
261
+ ];
262
+ const visited = new Set();
263
+ const queue = [func.id];
264
+ while (queue.length > 0) {
265
+ const current = queue.shift();
266
+ if (visited.has(current))
267
+ continue;
268
+ visited.add(current);
269
+ const node = graph.functions.get(current);
270
+ if (!node)
271
+ continue;
272
+ // Check if this function is auth-related
273
+ if (authPatterns.some(p => p.test(node.name))) {
274
+ return true;
275
+ }
276
+ // Check decorators/annotations
277
+ if (node.decorators?.some(d => authPatterns.some(p => p.test(d)))) {
278
+ return true;
279
+ }
280
+ // Add callees to queue
281
+ for (const call of node.calls ?? []) {
282
+ if (call.calleeId) {
283
+ queue.push(call.calleeId);
284
+ }
285
+ }
286
+ }
287
+ return false;
288
+ }
289
+ /**
290
+ * Detect validation patterns in call graph
291
+ */
292
+ detectValidationPatterns(graph) {
293
+ const invariants = [];
294
+ // Find entry points
295
+ const entryPointIds = graph.entryPoints ?? [];
296
+ const entryPoints = [];
297
+ for (const id of entryPointIds) {
298
+ const func = graph.functions.get(id);
299
+ if (func)
300
+ entryPoints.push(func);
301
+ }
302
+ if (entryPoints.length < 3)
303
+ return invariants;
304
+ // Check for validation patterns
305
+ const validationPatterns = [
306
+ /validate/i, /sanitize/i, /check/i, /verify/i,
307
+ /parse/i, /schema/i, /zod/i, /yup/i, /joi/i,
308
+ ];
309
+ const withValidation = [];
310
+ const withoutValidation = [];
311
+ for (const entry of entryPoints) {
312
+ const hasValidation = this.hasPatternInCallChain(entry, graph, validationPatterns);
313
+ if (hasValidation) {
314
+ withValidation.push(entry);
315
+ }
316
+ else {
317
+ withoutValidation.push(entry);
318
+ }
319
+ }
320
+ const total = withValidation.length + withoutValidation.length;
321
+ if (total >= 3 && withValidation.length / total >= 0.7) {
322
+ const confidence = withValidation.length / total;
323
+ invariants.push({
324
+ constraint: {
325
+ name: 'Input Validation Required',
326
+ description: 'Entry points must validate input before processing',
327
+ category: 'validation',
328
+ derivedFrom: {
329
+ patterns: [],
330
+ callGraphPaths: entryPoints.map(e => e.id),
331
+ boundaries: [],
332
+ },
333
+ invariant: {
334
+ type: 'must_precede',
335
+ condition: 'Input validation must occur at entry points',
336
+ predicate: {
337
+ entryPointMustHave: {
338
+ inCallChain: ['validate', 'sanitize', 'parse', 'schema'],
339
+ position: 'before_handler',
340
+ },
341
+ },
342
+ },
343
+ scope: {
344
+ entryPoints: true,
345
+ },
346
+ confidence: {
347
+ score: confidence,
348
+ evidence: withValidation.length,
349
+ violations: withoutValidation.length,
350
+ lastVerified: new Date().toISOString(),
351
+ },
352
+ enforcement: {
353
+ level: 'warning',
354
+ guidance: 'Add input validation at the entry point',
355
+ },
356
+ status: 'discovered',
357
+ language: 'all',
358
+ },
359
+ evidence: {
360
+ conforming: withValidation.length,
361
+ violating: withoutValidation.length,
362
+ conformingLocations: withValidation.slice(0, 5).map(f => `${f.file}:${f.startLine}`),
363
+ violatingLocations: withoutValidation.slice(0, 5).map(f => `${f.file}:${f.startLine}`),
364
+ sources: ['callGraph'],
365
+ },
366
+ violations: withoutValidation.map(f => ({
367
+ file: f.file,
368
+ line: f.startLine,
369
+ reason: 'Entry point lacks input validation',
370
+ })),
371
+ });
372
+ }
373
+ return invariants;
374
+ }
375
+ /**
376
+ * Check if a function has a pattern in its call chain
377
+ */
378
+ hasPatternInCallChain(func, graph, patterns) {
379
+ const visited = new Set();
380
+ const queue = [func.id];
381
+ while (queue.length > 0) {
382
+ const current = queue.shift();
383
+ if (visited.has(current))
384
+ continue;
385
+ visited.add(current);
386
+ const node = graph.functions.get(current);
387
+ if (!node)
388
+ continue;
389
+ if (patterns.some(p => p.test(node.name))) {
390
+ return true;
391
+ }
392
+ if (node.decorators?.some(d => patterns.some(p => p.test(d)))) {
393
+ return true;
394
+ }
395
+ for (const call of node.calls ?? []) {
396
+ if (call.calleeId) {
397
+ queue.push(call.calleeId);
398
+ }
399
+ }
400
+ }
401
+ return false;
402
+ }
403
+ // ===========================================================================
404
+ // Boundary-Based Detection
405
+ // ===========================================================================
406
+ /**
407
+ * Detect invariants from boundary data
408
+ */
409
+ async detectFromBoundaries(_options) {
410
+ const invariants = [];
411
+ const store = this.config.boundaryStore;
412
+ try {
413
+ await store.initialize();
414
+ const accessMap = store.getAccessMap();
415
+ if (!accessMap)
416
+ return invariants;
417
+ // Detect data access layer invariants from access points
418
+ const accessPoints = Object.values(accessMap.accessPoints);
419
+ if (accessPoints.length < 3)
420
+ return invariants;
421
+ // Group by table
422
+ const byTable = new Map();
423
+ for (const point of accessPoints) {
424
+ const table = point.table;
425
+ const list = byTable.get(table) ?? [];
426
+ list.push({
427
+ file: point.file,
428
+ accessor: point.context ?? 'direct',
429
+ line: point.line,
430
+ });
431
+ byTable.set(table, list);
432
+ }
433
+ // For each table with enough accesses, check for consistent access layer
434
+ for (const [table, accesses] of byTable) {
435
+ if (accesses.length < 3)
436
+ continue;
437
+ // Extract access layers
438
+ const layerCounts = new Map();
439
+ for (const access of accesses) {
440
+ const layer = this.extractAccessLayer(access.accessor);
441
+ layerCounts.set(layer, (layerCounts.get(layer) ?? 0) + 1);
442
+ }
443
+ // Find dominant layer
444
+ let dominantLayer = '';
445
+ let dominantCount = 0;
446
+ for (const [layer, count] of layerCounts) {
447
+ if (count > dominantCount) {
448
+ dominantLayer = layer;
449
+ dominantCount = count;
450
+ }
451
+ }
452
+ const confidence = dominantCount / accesses.length;
453
+ if (confidence >= 0.8 && dominantLayer && dominantLayer !== 'direct') {
454
+ const violations = accesses.filter(a => this.extractAccessLayer(a.accessor) !== dominantLayer);
455
+ invariants.push({
456
+ constraint: {
457
+ name: `${table} Access Layer`,
458
+ description: `Access to ${table} must go through ${dominantLayer}`,
459
+ category: 'data',
460
+ derivedFrom: {
461
+ patterns: [],
462
+ callGraphPaths: [],
463
+ boundaries: [table],
464
+ },
465
+ invariant: {
466
+ type: 'data_flow',
467
+ condition: `All access to ${table} must go through ${dominantLayer}`,
468
+ predicate: {
469
+ dataAccess: {
470
+ table,
471
+ mustGoThrough: [dominantLayer],
472
+ },
473
+ },
474
+ },
475
+ scope: {
476
+ dataAccessors: true,
477
+ },
478
+ confidence: {
479
+ score: confidence,
480
+ evidence: dominantCount,
481
+ violations: violations.length,
482
+ lastVerified: new Date().toISOString(),
483
+ },
484
+ enforcement: {
485
+ level: 'warning',
486
+ guidance: `Access ${table} through ${dominantLayer} instead of directly`,
487
+ },
488
+ status: 'discovered',
489
+ language: 'all',
490
+ },
491
+ evidence: {
492
+ conforming: dominantCount,
493
+ violating: violations.length,
494
+ conformingLocations: accesses
495
+ .filter(a => this.extractAccessLayer(a.accessor) === dominantLayer)
496
+ .slice(0, 5)
497
+ .map(a => `${a.file}:${a.line}`),
498
+ violatingLocations: violations.slice(0, 5).map(a => `${a.file}:${a.line}`),
499
+ sources: ['boundaries'],
500
+ },
501
+ violations: violations.map(a => ({
502
+ file: a.file,
503
+ line: a.line,
504
+ reason: `Accesses ${table} directly instead of through ${dominantLayer}`,
505
+ })),
506
+ });
507
+ }
508
+ }
509
+ // Detect sensitive data access patterns
510
+ const sensitiveInvariants = this.detectSensitiveDataInvariants(accessMap);
511
+ invariants.push(...sensitiveInvariants);
512
+ }
513
+ catch {
514
+ // Boundary store not available or error
515
+ }
516
+ return invariants;
517
+ }
518
+ /**
519
+ * Detect invariants for sensitive data access
520
+ */
521
+ detectSensitiveDataInvariants(accessMap) {
522
+ const invariants = [];
523
+ if (!accessMap.sensitiveFields || accessMap.sensitiveFields.length === 0) {
524
+ return invariants;
525
+ }
526
+ // Group sensitive fields by table
527
+ const sensitiveByTable = new Map();
528
+ for (const field of accessMap.sensitiveFields) {
529
+ if (!field.table)
530
+ continue; // Skip fields without table info
531
+ const fields = sensitiveByTable.get(field.table) ?? [];
532
+ fields.push(field.field);
533
+ sensitiveByTable.set(field.table, fields);
534
+ }
535
+ for (const [table, fields] of sensitiveByTable) {
536
+ invariants.push({
537
+ constraint: {
538
+ name: `${table} Sensitive Data Protection`,
539
+ description: `Sensitive fields in ${table} require special handling`,
540
+ category: 'security',
541
+ derivedFrom: {
542
+ patterns: [],
543
+ callGraphPaths: [],
544
+ boundaries: [table],
545
+ },
546
+ invariant: {
547
+ type: 'must_have',
548
+ condition: `Access to sensitive fields (${fields.join(', ')}) must be audited`,
549
+ predicate: {
550
+ dataAccess: {
551
+ table,
552
+ sensitiveFields: fields,
553
+ requiresAuth: true,
554
+ },
555
+ },
556
+ },
557
+ scope: {
558
+ dataAccessors: true,
559
+ },
560
+ confidence: {
561
+ score: 0.95,
562
+ evidence: fields.length,
563
+ violations: 0,
564
+ lastVerified: new Date().toISOString(),
565
+ },
566
+ enforcement: {
567
+ level: 'error',
568
+ guidance: `Ensure proper authorization and audit logging when accessing ${fields.join(', ')}`,
569
+ },
570
+ status: 'discovered',
571
+ language: 'all',
572
+ },
573
+ evidence: {
574
+ conforming: fields.length,
575
+ violating: 0,
576
+ conformingLocations: [],
577
+ violatingLocations: [],
578
+ sources: ['boundaries:sensitiveFields'],
579
+ },
580
+ violations: [],
581
+ });
582
+ }
583
+ return invariants;
584
+ }
585
+ /**
586
+ * Extract the access layer from an accessor context
587
+ */
588
+ extractAccessLayer(accessor) {
589
+ const match = accessor.match(/(\w+)(Repository|Service|DAO|Store|Manager)/i);
590
+ return match ? match[0] : 'direct';
591
+ }
592
+ // ===========================================================================
593
+ // Test Topology-Based Detection
594
+ // ===========================================================================
595
+ /**
596
+ * Detect invariants from test topology
597
+ */
598
+ async detectFromTestTopology(_options) {
599
+ const invariants = [];
600
+ const analyzer = this.config.testTopologyAnalyzer;
601
+ // Get summary statistics
602
+ const summary = analyzer.getSummary();
603
+ if (!summary || summary.totalFunctions < 5)
604
+ return invariants;
605
+ // If most functions are tested, create a test coverage invariant
606
+ const coverageRatio = summary.coveredFunctions / summary.totalFunctions;
607
+ if (coverageRatio >= 0.7) {
608
+ invariants.push({
609
+ constraint: {
610
+ name: 'Function Test Coverage',
611
+ description: 'Functions should have at least one test',
612
+ category: 'test',
613
+ derivedFrom: {
614
+ patterns: [],
615
+ callGraphPaths: [],
616
+ boundaries: [],
617
+ testTopology: ['coverage'],
618
+ },
619
+ invariant: {
620
+ type: 'must_have',
621
+ condition: 'Each function must have at least one test',
622
+ predicate: {
623
+ testCoverage: {
624
+ minCoverage: 1,
625
+ types: ['unit'],
626
+ },
627
+ },
628
+ },
629
+ scope: {
630
+ functions: ['.*'],
631
+ exclude: {
632
+ files: ['**/test/**', '**/*.test.*', '**/*.spec.*'],
633
+ },
634
+ },
635
+ confidence: {
636
+ score: coverageRatio,
637
+ evidence: summary.coveredFunctions,
638
+ violations: summary.totalFunctions - summary.coveredFunctions,
639
+ lastVerified: new Date().toISOString(),
640
+ },
641
+ enforcement: {
642
+ level: 'warning',
643
+ guidance: 'Add unit tests for this function',
644
+ },
645
+ status: 'discovered',
646
+ language: 'all',
647
+ },
648
+ evidence: {
649
+ conforming: summary.coveredFunctions,
650
+ violating: summary.totalFunctions - summary.coveredFunctions,
651
+ conformingLocations: [],
652
+ violatingLocations: [],
653
+ sources: ['testTopology'],
654
+ },
655
+ violations: [],
656
+ });
657
+ }
658
+ // Check mock ratio patterns
659
+ if (summary.avgMockRatio < 0.5) {
660
+ invariants.push({
661
+ constraint: {
662
+ name: 'Reasonable Mock Usage',
663
+ description: 'Tests should not over-mock - prefer integration over isolation',
664
+ category: 'test',
665
+ derivedFrom: {
666
+ patterns: [],
667
+ callGraphPaths: [],
668
+ boundaries: [],
669
+ testTopology: ['mocks'],
670
+ },
671
+ invariant: {
672
+ type: 'must_not_have',
673
+ condition: 'Tests should have mock ratio below 70%',
674
+ predicate: {
675
+ testCoverage: {
676
+ maxMockRatio: 0.7,
677
+ },
678
+ },
679
+ },
680
+ scope: {
681
+ files: ['**/*.test.*', '**/*.spec.*'],
682
+ },
683
+ confidence: {
684
+ score: 1 - summary.avgMockRatio,
685
+ evidence: summary.testCases,
686
+ violations: 0,
687
+ lastVerified: new Date().toISOString(),
688
+ },
689
+ enforcement: {
690
+ level: 'info',
691
+ guidance: 'Consider reducing mocks in favor of integration tests',
692
+ },
693
+ status: 'discovered',
694
+ language: 'all',
695
+ },
696
+ evidence: {
697
+ conforming: summary.testCases,
698
+ violating: 0,
699
+ conformingLocations: [],
700
+ violatingLocations: [],
701
+ sources: ['testTopology:mocks'],
702
+ },
703
+ violations: [],
704
+ });
705
+ }
706
+ return invariants;
707
+ }
708
+ // ===========================================================================
709
+ // Error Handling-Based Detection
710
+ // ===========================================================================
711
+ /**
712
+ * Detect invariants from error handling analysis
713
+ */
714
+ async detectFromErrorHandling(_options) {
715
+ const invariants = [];
716
+ const analyzer = this.config.errorHandlingAnalyzer;
717
+ // Get topology and summary
718
+ const topology = analyzer.getTopology();
719
+ const summary = analyzer.getSummary();
720
+ if (!topology || !summary || summary.totalFunctions < 5)
721
+ return invariants;
722
+ // Detect async error handling patterns
723
+ const asyncFunctions = [];
724
+ for (const [_funcId, profile] of topology.functions) {
725
+ if (profile.isAsync) {
726
+ asyncFunctions.push({
727
+ file: profile.file,
728
+ line: profile.line,
729
+ name: profile.qualifiedName,
730
+ hasHandling: profile.hasTryCatch || (profile.asyncHandling?.hasAsyncTryCatch ?? false),
731
+ });
732
+ }
733
+ }
734
+ if (asyncFunctions.length >= 5) {
735
+ const withHandling = asyncFunctions.filter(f => f.hasHandling);
736
+ const withoutHandling = asyncFunctions.filter(f => !f.hasHandling);
737
+ const ratio = withHandling.length / asyncFunctions.length;
738
+ if (ratio >= 0.7) {
739
+ invariants.push({
740
+ constraint: {
741
+ name: 'Async Error Handling',
742
+ description: 'Async functions must have error handling',
743
+ category: 'error',
744
+ derivedFrom: {
745
+ patterns: [],
746
+ callGraphPaths: [],
747
+ boundaries: [],
748
+ errorHandling: ['topology'],
749
+ },
750
+ invariant: {
751
+ type: 'must_have',
752
+ condition: 'Async functions must have try-catch or error handling',
753
+ predicate: {
754
+ functionMustHave: {
755
+ errorHandling: true,
756
+ isAsync: true,
757
+ },
758
+ },
759
+ },
760
+ scope: {
761
+ functions: ['.*'],
762
+ },
763
+ confidence: {
764
+ score: ratio,
765
+ evidence: withHandling.length,
766
+ violations: withoutHandling.length,
767
+ lastVerified: new Date().toISOString(),
768
+ },
769
+ enforcement: {
770
+ level: 'warning',
771
+ guidance: 'Add try-catch or error handling to this async function',
772
+ },
773
+ status: 'discovered',
774
+ language: 'all',
775
+ },
776
+ evidence: {
777
+ conforming: withHandling.length,
778
+ violating: withoutHandling.length,
779
+ conformingLocations: withHandling.slice(0, 5).map(f => `${f.file}:${f.line}`),
780
+ violatingLocations: withoutHandling.slice(0, 5).map(f => `${f.file}:${f.line}`),
781
+ sources: ['errorHandling'],
782
+ },
783
+ violations: withoutHandling.slice(0, 20).map(f => ({
784
+ file: f.file,
785
+ line: f.line,
786
+ reason: 'Async function lacks error handling',
787
+ })),
788
+ });
789
+ }
790
+ }
791
+ // Detect error boundary patterns
792
+ const boundaries = topology.boundaries ?? [];
793
+ if (boundaries.length >= 2) {
794
+ const frameworkBoundaries = boundaries.filter(b => b.isFrameworkBoundary);
795
+ if (frameworkBoundaries.length > 0) {
796
+ invariants.push({
797
+ constraint: {
798
+ name: 'Error Boundary Pattern',
799
+ description: 'Use framework error boundaries for centralized error handling',
800
+ category: 'error',
801
+ derivedFrom: {
802
+ patterns: [],
803
+ callGraphPaths: [],
804
+ boundaries: [],
805
+ errorHandling: ['boundaries'],
806
+ },
807
+ invariant: {
808
+ type: 'must_have',
809
+ condition: 'Critical paths should be protected by error boundaries',
810
+ predicate: {
811
+ callChain: {
812
+ from: 'entryPoint',
813
+ to: 'dataAccess',
814
+ mustInclude: frameworkBoundaries.map(b => b.name),
815
+ },
816
+ },
817
+ },
818
+ scope: {
819
+ entryPoints: true,
820
+ },
821
+ confidence: {
822
+ score: 0.85,
823
+ evidence: frameworkBoundaries.length,
824
+ violations: 0,
825
+ lastVerified: new Date().toISOString(),
826
+ },
827
+ enforcement: {
828
+ level: 'info',
829
+ guidance: 'Ensure error boundaries protect critical code paths',
830
+ },
831
+ status: 'discovered',
832
+ language: 'all',
833
+ },
834
+ evidence: {
835
+ conforming: frameworkBoundaries.length,
836
+ violating: 0,
837
+ conformingLocations: frameworkBoundaries.slice(0, 5).map(b => `${b.file}:${b.line}`),
838
+ violatingLocations: [],
839
+ sources: ['errorHandling:boundaries'],
840
+ },
841
+ violations: [],
842
+ });
843
+ }
844
+ }
845
+ // Detect swallowed error anti-pattern
846
+ const swallowedCount = summary.topIssues?.find(i => i.type === 'swallowed')?.count ?? 0;
847
+ if (swallowedCount > 0 && summary.totalFunctions > 10) {
848
+ const swallowRatio = swallowedCount / summary.totalFunctions;
849
+ if (swallowRatio < 0.1) { // Less than 10% swallow errors = good pattern
850
+ invariants.push({
851
+ constraint: {
852
+ name: 'No Swallowed Errors',
853
+ description: 'Errors must not be silently swallowed',
854
+ category: 'error',
855
+ derivedFrom: {
856
+ patterns: [],
857
+ callGraphPaths: [],
858
+ boundaries: [],
859
+ errorHandling: ['gaps'],
860
+ },
861
+ invariant: {
862
+ type: 'must_not_have',
863
+ condition: 'Catch blocks must not swallow errors silently',
864
+ predicate: {
865
+ functionMustHave: {
866
+ bodyMustNotContain: ['catch {}', 'catch (e) {}', 'except: pass'],
867
+ },
868
+ },
869
+ },
870
+ scope: {
871
+ functions: ['.*'],
872
+ },
873
+ confidence: {
874
+ score: 1 - swallowRatio,
875
+ evidence: summary.totalFunctions - swallowedCount,
876
+ violations: swallowedCount,
877
+ lastVerified: new Date().toISOString(),
878
+ },
879
+ enforcement: {
880
+ level: 'error',
881
+ guidance: 'Log the error or rethrow it instead of swallowing',
882
+ },
883
+ status: 'discovered',
884
+ language: 'all',
885
+ },
886
+ evidence: {
887
+ conforming: summary.totalFunctions - swallowedCount,
888
+ violating: swallowedCount,
889
+ conformingLocations: [],
890
+ violatingLocations: [],
891
+ sources: ['errorHandling:gaps'],
892
+ },
893
+ violations: [],
894
+ });
895
+ }
896
+ }
897
+ return invariants;
898
+ }
899
+ // ===========================================================================
900
+ // Helper Methods
901
+ // ===========================================================================
902
+ detectLanguageFromPattern(pattern) {
903
+ const extensions = new Set();
904
+ for (const loc of pattern.locations) {
905
+ const ext = loc.file.split('.').pop()?.toLowerCase();
906
+ if (ext)
907
+ extensions.add(ext);
908
+ }
909
+ if (extensions.has('ts') || extensions.has('tsx'))
910
+ return 'typescript';
911
+ if (extensions.has('js') || extensions.has('jsx'))
912
+ return 'javascript';
913
+ if (extensions.has('py'))
914
+ return 'python';
915
+ if (extensions.has('java'))
916
+ return 'java';
917
+ if (extensions.has('cs'))
918
+ return 'csharp';
919
+ if (extensions.has('php'))
920
+ return 'php';
921
+ return 'all';
922
+ }
923
+ buildPredicateFromPattern(pattern) {
924
+ const predicate = {};
925
+ const config = pattern.detector;
926
+ if (config?.config && typeof config.config === 'object') {
927
+ const detectorConfig = config.config;
928
+ if (Array.isArray(detectorConfig['decorators']) && detectorConfig['decorators'].length > 0) {
929
+ predicate.functionMustHave = {
930
+ decorator: detectorConfig['decorators'],
931
+ };
932
+ }
933
+ if (typeof detectorConfig['namePattern'] === 'string') {
934
+ predicate.naming = {
935
+ pattern: detectorConfig['namePattern'],
936
+ scope: 'function',
937
+ };
938
+ }
939
+ }
940
+ return predicate;
941
+ }
942
+ inferConstraintType(pattern) {
943
+ const category = pattern.category;
944
+ switch (category) {
945
+ case 'auth':
946
+ return 'must_precede';
947
+ case 'errors':
948
+ return 'must_wrap';
949
+ case 'logging':
950
+ return 'must_have';
951
+ case 'testing':
952
+ return 'must_have';
953
+ case 'security':
954
+ return 'must_have';
955
+ default:
956
+ return 'must_have';
957
+ }
958
+ }
959
+ buildScopeFromPattern(pattern) {
960
+ const scope = {};
961
+ const directories = new Set();
962
+ for (const loc of pattern.locations) {
963
+ const dir = loc.file.split('/').slice(0, -1).join('/');
964
+ if (dir)
965
+ directories.add(dir);
966
+ }
967
+ if (directories.size > 0) {
968
+ scope.files = Array.from(directories).map(d => `${d}/**/*`);
969
+ }
970
+ return scope;
971
+ }
972
+ }
973
+ // =============================================================================
974
+ // Factory
975
+ // =============================================================================
976
+ export function createInvariantDetector(config) {
977
+ return new InvariantDetector(config);
978
+ }
979
+ //# sourceMappingURL=invariant-detector.js.map