agentic-qe 3.2.3 → 3.3.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 (658) hide show
  1. package/.claude/agents/v3/qe-accessibility-auditor.md +90 -0
  2. package/README.md +49 -7
  3. package/package.json +8 -2
  4. package/scripts/cloud-db-config.json +37 -0
  5. package/scripts/cloud-db-connect.sh +37 -0
  6. package/scripts/cloud-db-tunnel.sh +23 -0
  7. package/v3/CHANGELOG.md +253 -0
  8. package/v3/README.md +59 -1
  9. package/v3/assets/agents/v3/qe-accessibility-auditor.md +90 -0
  10. package/v3/dist/adapters/claude-flow/index.d.ts +54 -0
  11. package/v3/dist/adapters/claude-flow/index.d.ts.map +1 -0
  12. package/v3/dist/adapters/claude-flow/index.js +79 -0
  13. package/v3/dist/adapters/claude-flow/index.js.map +1 -0
  14. package/v3/dist/adapters/claude-flow/model-router-bridge.d.ts +70 -0
  15. package/v3/dist/adapters/claude-flow/model-router-bridge.d.ts.map +1 -0
  16. package/v3/dist/adapters/claude-flow/model-router-bridge.js +203 -0
  17. package/v3/dist/adapters/claude-flow/model-router-bridge.js.map +1 -0
  18. package/v3/dist/adapters/claude-flow/pretrain-bridge.d.ts +73 -0
  19. package/v3/dist/adapters/claude-flow/pretrain-bridge.d.ts.map +1 -0
  20. package/v3/dist/adapters/claude-flow/pretrain-bridge.js +276 -0
  21. package/v3/dist/adapters/claude-flow/pretrain-bridge.js.map +1 -0
  22. package/v3/dist/adapters/claude-flow/trajectory-bridge.d.ts +70 -0
  23. package/v3/dist/adapters/claude-flow/trajectory-bridge.d.ts.map +1 -0
  24. package/v3/dist/adapters/claude-flow/trajectory-bridge.js +205 -0
  25. package/v3/dist/adapters/claude-flow/trajectory-bridge.js.map +1 -0
  26. package/v3/dist/adapters/claude-flow/types.d.ts +99 -0
  27. package/v3/dist/adapters/claude-flow/types.d.ts.map +1 -0
  28. package/v3/dist/adapters/claude-flow/types.js +6 -0
  29. package/v3/dist/adapters/claude-flow/types.js.map +1 -0
  30. package/v3/dist/causal-discovery/causal-graph.d.ts +80 -1
  31. package/v3/dist/causal-discovery/causal-graph.d.ts.map +1 -1
  32. package/v3/dist/causal-discovery/causal-graph.js +111 -1
  33. package/v3/dist/causal-discovery/causal-graph.js.map +1 -1
  34. package/v3/dist/cli/bundle.js +25321 -15378
  35. package/v3/dist/cli/command-registry.d.ts +55 -0
  36. package/v3/dist/cli/command-registry.d.ts.map +1 -0
  37. package/v3/dist/cli/command-registry.js +103 -0
  38. package/v3/dist/cli/command-registry.js.map +1 -0
  39. package/v3/dist/cli/commands/claude-flow-setup.d.ts +82 -0
  40. package/v3/dist/cli/commands/claude-flow-setup.d.ts.map +1 -0
  41. package/v3/dist/cli/commands/claude-flow-setup.js +334 -0
  42. package/v3/dist/cli/commands/claude-flow-setup.js.map +1 -0
  43. package/v3/dist/cli/commands/code.d.ts +9 -0
  44. package/v3/dist/cli/commands/code.d.ts.map +1 -0
  45. package/v3/dist/cli/commands/code.js +254 -0
  46. package/v3/dist/cli/commands/code.js.map +1 -0
  47. package/v3/dist/cli/commands/completions.d.ts +8 -0
  48. package/v3/dist/cli/commands/completions.d.ts.map +1 -0
  49. package/v3/dist/cli/commands/completions.js +99 -0
  50. package/v3/dist/cli/commands/completions.js.map +1 -0
  51. package/v3/dist/cli/commands/coverage.d.ts +9 -0
  52. package/v3/dist/cli/commands/coverage.d.ts.map +1 -0
  53. package/v3/dist/cli/commands/coverage.js +208 -0
  54. package/v3/dist/cli/commands/coverage.js.map +1 -0
  55. package/v3/dist/cli/commands/fleet.d.ts +11 -0
  56. package/v3/dist/cli/commands/fleet.d.ts.map +1 -0
  57. package/v3/dist/cli/commands/fleet.js +338 -0
  58. package/v3/dist/cli/commands/fleet.js.map +1 -0
  59. package/v3/dist/cli/commands/hooks.d.ts +2 -0
  60. package/v3/dist/cli/commands/hooks.d.ts.map +1 -1
  61. package/v3/dist/cli/commands/hooks.js +13 -2
  62. package/v3/dist/cli/commands/hooks.js.map +1 -1
  63. package/v3/dist/cli/commands/init.d.ts +19 -0
  64. package/v3/dist/cli/commands/init.d.ts.map +1 -0
  65. package/v3/dist/cli/commands/init.js +345 -0
  66. package/v3/dist/cli/commands/init.js.map +1 -0
  67. package/v3/dist/cli/commands/migrate.d.ts +9 -0
  68. package/v3/dist/cli/commands/migrate.d.ts.map +1 -0
  69. package/v3/dist/cli/commands/migrate.js +566 -0
  70. package/v3/dist/cli/commands/migrate.js.map +1 -0
  71. package/v3/dist/cli/commands/quality.d.ts +9 -0
  72. package/v3/dist/cli/commands/quality.d.ts.map +1 -0
  73. package/v3/dist/cli/commands/quality.js +40 -0
  74. package/v3/dist/cli/commands/quality.js.map +1 -0
  75. package/v3/dist/cli/commands/security.d.ts +9 -0
  76. package/v3/dist/cli/commands/security.d.ts.map +1 -0
  77. package/v3/dist/cli/commands/security.js +124 -0
  78. package/v3/dist/cli/commands/security.js.map +1 -0
  79. package/v3/dist/cli/commands/sync.d.ts +19 -0
  80. package/v3/dist/cli/commands/sync.d.ts.map +1 -0
  81. package/v3/dist/cli/commands/sync.js +283 -0
  82. package/v3/dist/cli/commands/sync.js.map +1 -0
  83. package/v3/dist/cli/commands/test.d.ts +9 -0
  84. package/v3/dist/cli/commands/test.d.ts.map +1 -0
  85. package/v3/dist/cli/commands/test.js +166 -0
  86. package/v3/dist/cli/commands/test.js.map +1 -0
  87. package/v3/dist/cli/handlers/agent-handler.d.ts +20 -0
  88. package/v3/dist/cli/handlers/agent-handler.d.ts.map +1 -0
  89. package/v3/dist/cli/handlers/agent-handler.js +158 -0
  90. package/v3/dist/cli/handlers/agent-handler.js.map +1 -0
  91. package/v3/dist/cli/handlers/domain-handler.d.ts +20 -0
  92. package/v3/dist/cli/handlers/domain-handler.d.ts.map +1 -0
  93. package/v3/dist/cli/handlers/domain-handler.js +115 -0
  94. package/v3/dist/cli/handlers/domain-handler.js.map +1 -0
  95. package/v3/dist/cli/handlers/index.d.ts +13 -0
  96. package/v3/dist/cli/handlers/index.d.ts.map +1 -0
  97. package/v3/dist/cli/handlers/index.js +15 -0
  98. package/v3/dist/cli/handlers/index.js.map +1 -0
  99. package/v3/dist/cli/handlers/init-handler.d.ts +38 -0
  100. package/v3/dist/cli/handlers/init-handler.d.ts.map +1 -0
  101. package/v3/dist/cli/handlers/init-handler.js +288 -0
  102. package/v3/dist/cli/handlers/init-handler.js.map +1 -0
  103. package/v3/dist/cli/handlers/interfaces.d.ts +104 -0
  104. package/v3/dist/cli/handlers/interfaces.d.ts.map +1 -0
  105. package/v3/dist/cli/handlers/interfaces.js +109 -0
  106. package/v3/dist/cli/handlers/interfaces.js.map +1 -0
  107. package/v3/dist/cli/handlers/protocol-handler.d.ts +19 -0
  108. package/v3/dist/cli/handlers/protocol-handler.d.ts.map +1 -0
  109. package/v3/dist/cli/handlers/protocol-handler.js +79 -0
  110. package/v3/dist/cli/handlers/protocol-handler.js.map +1 -0
  111. package/v3/dist/cli/handlers/status-handler.d.ts +30 -0
  112. package/v3/dist/cli/handlers/status-handler.d.ts.map +1 -0
  113. package/v3/dist/cli/handlers/status-handler.js +218 -0
  114. package/v3/dist/cli/handlers/status-handler.js.map +1 -0
  115. package/v3/dist/cli/handlers/task-handler.d.ts +22 -0
  116. package/v3/dist/cli/handlers/task-handler.d.ts.map +1 -0
  117. package/v3/dist/cli/handlers/task-handler.js +271 -0
  118. package/v3/dist/cli/handlers/task-handler.js.map +1 -0
  119. package/v3/dist/cli/index.d.ts +4 -0
  120. package/v3/dist/cli/index.d.ts.map +1 -1
  121. package/v3/dist/cli/index.js +62 -2583
  122. package/v3/dist/cli/index.js.map +1 -1
  123. package/v3/dist/cli/wizards/core/index.d.ts +11 -0
  124. package/v3/dist/cli/wizards/core/index.d.ts.map +1 -0
  125. package/v3/dist/cli/wizards/core/index.js +15 -0
  126. package/v3/dist/cli/wizards/core/index.js.map +1 -0
  127. package/v3/dist/cli/wizards/core/wizard-base.d.ts +87 -0
  128. package/v3/dist/cli/wizards/core/wizard-base.d.ts.map +1 -0
  129. package/v3/dist/cli/wizards/core/wizard-base.js +120 -0
  130. package/v3/dist/cli/wizards/core/wizard-base.js.map +1 -0
  131. package/v3/dist/cli/wizards/core/wizard-command.d.ts +182 -0
  132. package/v3/dist/cli/wizards/core/wizard-command.d.ts.map +1 -0
  133. package/v3/dist/cli/wizards/core/wizard-command.js +45 -0
  134. package/v3/dist/cli/wizards/core/wizard-command.js.map +1 -0
  135. package/v3/dist/cli/wizards/core/wizard-step.d.ts +109 -0
  136. package/v3/dist/cli/wizards/core/wizard-step.d.ts.map +1 -0
  137. package/v3/dist/cli/wizards/core/wizard-step.js +384 -0
  138. package/v3/dist/cli/wizards/core/wizard-step.js.map +1 -0
  139. package/v3/dist/cli/wizards/core/wizard-utils.d.ts +117 -0
  140. package/v3/dist/cli/wizards/core/wizard-utils.d.ts.map +1 -0
  141. package/v3/dist/cli/wizards/core/wizard-utils.js +291 -0
  142. package/v3/dist/cli/wizards/core/wizard-utils.js.map +1 -0
  143. package/v3/dist/cli/wizards/coverage-wizard.d.ts +13 -68
  144. package/v3/dist/cli/wizards/coverage-wizard.d.ts.map +1 -1
  145. package/v3/dist/cli/wizards/coverage-wizard.js +127 -391
  146. package/v3/dist/cli/wizards/coverage-wizard.js.map +1 -1
  147. package/v3/dist/cli/wizards/fleet-wizard.d.ts +13 -64
  148. package/v3/dist/cli/wizards/fleet-wizard.d.ts.map +1 -1
  149. package/v3/dist/cli/wizards/fleet-wizard.js +150 -363
  150. package/v3/dist/cli/wizards/fleet-wizard.js.map +1 -1
  151. package/v3/dist/cli/wizards/index.d.ts +2 -0
  152. package/v3/dist/cli/wizards/index.d.ts.map +1 -1
  153. package/v3/dist/cli/wizards/index.js +3 -0
  154. package/v3/dist/cli/wizards/index.js.map +1 -1
  155. package/v3/dist/cli/wizards/security-wizard.d.ts +13 -64
  156. package/v3/dist/cli/wizards/security-wizard.d.ts.map +1 -1
  157. package/v3/dist/cli/wizards/security-wizard.js +152 -395
  158. package/v3/dist/cli/wizards/security-wizard.js.map +1 -1
  159. package/v3/dist/cli/wizards/test-wizard.d.ts +13 -77
  160. package/v3/dist/cli/wizards/test-wizard.d.ts.map +1 -1
  161. package/v3/dist/cli/wizards/test-wizard.js +196 -328
  162. package/v3/dist/cli/wizards/test-wizard.js.map +1 -1
  163. package/v3/dist/coordination/mincut/interfaces.d.ts +8 -2
  164. package/v3/dist/coordination/mincut/interfaces.d.ts.map +1 -1
  165. package/v3/dist/coordination/mincut/interfaces.js.map +1 -1
  166. package/v3/dist/coordination/mincut/mincut-health-monitor.d.ts +8 -0
  167. package/v3/dist/coordination/mincut/mincut-health-monitor.d.ts.map +1 -1
  168. package/v3/dist/coordination/mincut/mincut-health-monitor.js +26 -4
  169. package/v3/dist/coordination/mincut/mincut-health-monitor.js.map +1 -1
  170. package/v3/dist/coordination/mincut/queen-integration.d.ts +7 -0
  171. package/v3/dist/coordination/mincut/queen-integration.d.ts.map +1 -1
  172. package/v3/dist/coordination/mincut/queen-integration.js +19 -1
  173. package/v3/dist/coordination/mincut/queen-integration.js.map +1 -1
  174. package/v3/dist/coordination/queen-coordinator.d.ts +5 -0
  175. package/v3/dist/coordination/queen-coordinator.d.ts.map +1 -1
  176. package/v3/dist/coordination/queen-coordinator.js +45 -7
  177. package/v3/dist/coordination/queen-coordinator.js.map +1 -1
  178. package/v3/dist/coordination/task-executor.js +2 -2
  179. package/v3/dist/coordination/task-executor.js.map +1 -1
  180. package/v3/dist/domains/chaos-resilience/plugin.js +2 -2
  181. package/v3/dist/domains/chaos-resilience/plugin.js.map +1 -1
  182. package/v3/dist/domains/code-intelligence/plugin.js +2 -2
  183. package/v3/dist/domains/code-intelligence/plugin.js.map +1 -1
  184. package/v3/dist/domains/contract-testing/plugin.js +2 -2
  185. package/v3/dist/domains/contract-testing/plugin.js.map +1 -1
  186. package/v3/dist/domains/coverage-analysis/plugin.d.ts.map +1 -1
  187. package/v3/dist/domains/coverage-analysis/plugin.js +2 -1
  188. package/v3/dist/domains/coverage-analysis/plugin.js.map +1 -1
  189. package/v3/dist/domains/defect-intelligence/plugin.js +2 -2
  190. package/v3/dist/domains/defect-intelligence/plugin.js.map +1 -1
  191. package/v3/dist/domains/domain-interface.d.ts.map +1 -1
  192. package/v3/dist/domains/domain-interface.js +3 -1
  193. package/v3/dist/domains/domain-interface.js.map +1 -1
  194. package/v3/dist/domains/learning-optimization/coordinator.d.ts +5 -0
  195. package/v3/dist/domains/learning-optimization/coordinator.d.ts.map +1 -1
  196. package/v3/dist/domains/learning-optimization/coordinator.js +79 -0
  197. package/v3/dist/domains/learning-optimization/coordinator.js.map +1 -1
  198. package/v3/dist/domains/learning-optimization/plugin.js +2 -2
  199. package/v3/dist/domains/learning-optimization/plugin.js.map +1 -1
  200. package/v3/dist/domains/quality-assessment/plugin.js +2 -2
  201. package/v3/dist/domains/quality-assessment/plugin.js.map +1 -1
  202. package/v3/dist/domains/requirements-validation/plugin.js +2 -2
  203. package/v3/dist/domains/requirements-validation/plugin.js.map +1 -1
  204. package/v3/dist/domains/security-compliance/plugin.js +2 -2
  205. package/v3/dist/domains/security-compliance/plugin.js.map +1 -1
  206. package/v3/dist/domains/test-execution/index.d.ts +2 -1
  207. package/v3/dist/domains/test-execution/index.d.ts.map +1 -1
  208. package/v3/dist/domains/test-execution/index.js +0 -2
  209. package/v3/dist/domains/test-execution/index.js.map +1 -1
  210. package/v3/dist/domains/test-execution/interfaces.d.ts +222 -25
  211. package/v3/dist/domains/test-execution/interfaces.d.ts.map +1 -1
  212. package/v3/dist/domains/test-execution/interfaces.js +130 -3
  213. package/v3/dist/domains/test-execution/interfaces.js.map +1 -1
  214. package/v3/dist/domains/test-execution/plugin.d.ts.map +1 -1
  215. package/v3/dist/domains/test-execution/plugin.js +2 -1
  216. package/v3/dist/domains/test-execution/plugin.js.map +1 -1
  217. package/v3/dist/domains/test-execution/test-prioritization-types.d.ts +5 -172
  218. package/v3/dist/domains/test-execution/test-prioritization-types.d.ts.map +1 -1
  219. package/v3/dist/domains/test-execution/test-prioritization-types.js +6 -129
  220. package/v3/dist/domains/test-execution/test-prioritization-types.js.map +1 -1
  221. package/v3/dist/domains/test-execution/types/index.d.ts +7 -3
  222. package/v3/dist/domains/test-execution/types/index.d.ts.map +1 -1
  223. package/v3/dist/domains/test-execution/types/index.js +7 -17
  224. package/v3/dist/domains/test-execution/types/index.js.map +1 -1
  225. package/v3/dist/domains/test-generation/coordinator.d.ts +32 -1
  226. package/v3/dist/domains/test-generation/coordinator.d.ts.map +1 -1
  227. package/v3/dist/domains/test-generation/coordinator.js +72 -3
  228. package/v3/dist/domains/test-generation/coordinator.js.map +1 -1
  229. package/v3/dist/domains/test-generation/factories/index.d.ts +8 -0
  230. package/v3/dist/domains/test-generation/factories/index.d.ts.map +1 -0
  231. package/v3/dist/domains/test-generation/factories/index.js +8 -0
  232. package/v3/dist/domains/test-generation/factories/index.js.map +1 -0
  233. package/v3/dist/domains/test-generation/factories/test-generator-factory.d.ts +108 -0
  234. package/v3/dist/domains/test-generation/factories/test-generator-factory.d.ts.map +1 -0
  235. package/v3/dist/domains/test-generation/factories/test-generator-factory.js +158 -0
  236. package/v3/dist/domains/test-generation/factories/test-generator-factory.js.map +1 -0
  237. package/v3/dist/domains/test-generation/generators/base-test-generator.d.ts +79 -0
  238. package/v3/dist/domains/test-generation/generators/base-test-generator.d.ts.map +1 -0
  239. package/v3/dist/domains/test-generation/generators/base-test-generator.js +252 -0
  240. package/v3/dist/domains/test-generation/generators/base-test-generator.js.map +1 -0
  241. package/v3/dist/domains/test-generation/generators/index.d.ts +11 -0
  242. package/v3/dist/domains/test-generation/generators/index.d.ts.map +1 -0
  243. package/v3/dist/domains/test-generation/generators/index.js +13 -0
  244. package/v3/dist/domains/test-generation/generators/index.js.map +1 -0
  245. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.d.ts +77 -0
  246. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.d.ts.map +1 -0
  247. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.js +365 -0
  248. package/v3/dist/domains/test-generation/generators/jest-vitest-generator.js.map +1 -0
  249. package/v3/dist/domains/test-generation/generators/mocha-generator.d.ts +56 -0
  250. package/v3/dist/domains/test-generation/generators/mocha-generator.d.ts.map +1 -0
  251. package/v3/dist/domains/test-generation/generators/mocha-generator.js +197 -0
  252. package/v3/dist/domains/test-generation/generators/mocha-generator.js.map +1 -0
  253. package/v3/dist/domains/test-generation/generators/pytest-generator.d.ts +66 -0
  254. package/v3/dist/domains/test-generation/generators/pytest-generator.d.ts.map +1 -0
  255. package/v3/dist/domains/test-generation/generators/pytest-generator.js +240 -0
  256. package/v3/dist/domains/test-generation/generators/pytest-generator.js.map +1 -0
  257. package/v3/dist/domains/test-generation/index.d.ts +2 -1
  258. package/v3/dist/domains/test-generation/index.d.ts.map +1 -1
  259. package/v3/dist/domains/test-generation/index.js +5 -1
  260. package/v3/dist/domains/test-generation/index.js.map +1 -1
  261. package/v3/dist/domains/test-generation/interfaces/index.d.ts +9 -0
  262. package/v3/dist/domains/test-generation/interfaces/index.d.ts.map +1 -0
  263. package/v3/dist/domains/test-generation/interfaces/index.js +9 -0
  264. package/v3/dist/domains/test-generation/interfaces/index.js.map +1 -0
  265. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.d.ts +166 -0
  266. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.d.ts.map +1 -0
  267. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.js +8 -0
  268. package/v3/dist/domains/test-generation/interfaces/test-generator.interface.js.map +1 -0
  269. package/v3/dist/domains/test-generation/interfaces.d.ts +163 -24
  270. package/v3/dist/domains/test-generation/interfaces.d.ts.map +1 -1
  271. package/v3/dist/domains/test-generation/interfaces.js +2 -2
  272. package/v3/dist/domains/test-generation/plugin.d.ts.map +1 -1
  273. package/v3/dist/domains/test-generation/plugin.js +6 -5
  274. package/v3/dist/domains/test-generation/plugin.js.map +1 -1
  275. package/v3/dist/domains/test-generation/services/coherence-gate-service.d.ts +245 -0
  276. package/v3/dist/domains/test-generation/services/coherence-gate-service.d.ts.map +1 -0
  277. package/v3/dist/domains/test-generation/services/coherence-gate-service.js +454 -0
  278. package/v3/dist/domains/test-generation/services/coherence-gate-service.js.map +1 -0
  279. package/v3/dist/domains/test-generation/services/index.d.ts +8 -1
  280. package/v3/dist/domains/test-generation/services/index.d.ts.map +1 -1
  281. package/v3/dist/domains/test-generation/services/index.js +10 -1
  282. package/v3/dist/domains/test-generation/services/index.js.map +1 -1
  283. package/v3/dist/domains/test-generation/services/property-test-generator.d.ts +34 -0
  284. package/v3/dist/domains/test-generation/services/property-test-generator.d.ts.map +1 -0
  285. package/v3/dist/domains/test-generation/services/property-test-generator.js +306 -0
  286. package/v3/dist/domains/test-generation/services/property-test-generator.js.map +1 -0
  287. package/v3/dist/domains/test-generation/services/tdd-generator.d.ts +33 -0
  288. package/v3/dist/domains/test-generation/services/tdd-generator.d.ts.map +1 -0
  289. package/v3/dist/domains/test-generation/services/tdd-generator.js +342 -0
  290. package/v3/dist/domains/test-generation/services/tdd-generator.js.map +1 -0
  291. package/v3/dist/domains/test-generation/services/test-data-generator.d.ts +34 -0
  292. package/v3/dist/domains/test-generation/services/test-data-generator.d.ts.map +1 -0
  293. package/v3/dist/domains/test-generation/services/test-data-generator.js +245 -0
  294. package/v3/dist/domains/test-generation/services/test-data-generator.js.map +1 -0
  295. package/v3/dist/domains/test-generation/services/test-generator.d.ts +51 -160
  296. package/v3/dist/domains/test-generation/services/test-generator.d.ts.map +1 -1
  297. package/v3/dist/domains/test-generation/services/test-generator.js +101 -1858
  298. package/v3/dist/domains/test-generation/services/test-generator.js.map +1 -1
  299. package/v3/dist/domains/visual-accessibility/index.d.ts +2 -1
  300. package/v3/dist/domains/visual-accessibility/index.d.ts.map +1 -1
  301. package/v3/dist/domains/visual-accessibility/index.js +1 -0
  302. package/v3/dist/domains/visual-accessibility/index.js.map +1 -1
  303. package/v3/dist/domains/visual-accessibility/interfaces.d.ts +131 -0
  304. package/v3/dist/domains/visual-accessibility/interfaces.d.ts.map +1 -1
  305. package/v3/dist/domains/visual-accessibility/plugin.d.ts +26 -0
  306. package/v3/dist/domains/visual-accessibility/plugin.d.ts.map +1 -1
  307. package/v3/dist/domains/visual-accessibility/plugin.js +153 -2
  308. package/v3/dist/domains/visual-accessibility/plugin.js.map +1 -1
  309. package/v3/dist/domains/visual-accessibility/services/accessibility-tester.d.ts +42 -1
  310. package/v3/dist/domains/visual-accessibility/services/accessibility-tester.d.ts.map +1 -1
  311. package/v3/dist/domains/visual-accessibility/services/accessibility-tester.js +69 -0
  312. package/v3/dist/domains/visual-accessibility/services/accessibility-tester.js.map +1 -1
  313. package/v3/dist/domains/visual-accessibility/services/eu-compliance.d.ts +138 -0
  314. package/v3/dist/domains/visual-accessibility/services/eu-compliance.d.ts.map +1 -0
  315. package/v3/dist/domains/visual-accessibility/services/eu-compliance.js +830 -0
  316. package/v3/dist/domains/visual-accessibility/services/eu-compliance.js.map +1 -0
  317. package/v3/dist/domains/visual-accessibility/services/index.d.ts +1 -0
  318. package/v3/dist/domains/visual-accessibility/services/index.d.ts.map +1 -1
  319. package/v3/dist/domains/visual-accessibility/services/index.js +1 -0
  320. package/v3/dist/domains/visual-accessibility/services/index.js.map +1 -1
  321. package/v3/dist/init/enhancements/claude-flow-adapter.d.ts +84 -0
  322. package/v3/dist/init/enhancements/claude-flow-adapter.d.ts.map +1 -0
  323. package/v3/dist/init/enhancements/claude-flow-adapter.js +250 -0
  324. package/v3/dist/init/enhancements/claude-flow-adapter.js.map +1 -0
  325. package/v3/dist/init/enhancements/detector.d.ts +10 -0
  326. package/v3/dist/init/enhancements/detector.d.ts.map +1 -0
  327. package/v3/dist/init/enhancements/detector.js +87 -0
  328. package/v3/dist/init/enhancements/detector.js.map +1 -0
  329. package/v3/dist/init/enhancements/index.d.ts +13 -0
  330. package/v3/dist/init/enhancements/index.d.ts.map +1 -0
  331. package/v3/dist/init/enhancements/index.js +25 -0
  332. package/v3/dist/init/enhancements/index.js.map +1 -0
  333. package/v3/dist/init/enhancements/types.d.ts +93 -0
  334. package/v3/dist/init/enhancements/types.d.ts.map +1 -0
  335. package/v3/dist/init/enhancements/types.js +6 -0
  336. package/v3/dist/init/enhancements/types.js.map +1 -0
  337. package/v3/dist/init/index.d.ts +8 -0
  338. package/v3/dist/init/index.d.ts.map +1 -1
  339. package/v3/dist/init/index.js +4 -0
  340. package/v3/dist/init/index.js.map +1 -1
  341. package/v3/dist/init/migration/config-migrator.d.ts +31 -0
  342. package/v3/dist/init/migration/config-migrator.d.ts.map +1 -0
  343. package/v3/dist/init/migration/config-migrator.js +133 -0
  344. package/v3/dist/init/migration/config-migrator.js.map +1 -0
  345. package/v3/dist/init/migration/data-migrator.d.ts +72 -0
  346. package/v3/dist/init/migration/data-migrator.d.ts.map +1 -0
  347. package/v3/dist/init/migration/data-migrator.js +233 -0
  348. package/v3/dist/init/migration/data-migrator.js.map +1 -0
  349. package/v3/dist/init/migration/detector.d.ts +44 -0
  350. package/v3/dist/init/migration/detector.d.ts.map +1 -0
  351. package/v3/dist/init/migration/detector.js +106 -0
  352. package/v3/dist/init/migration/detector.js.map +1 -0
  353. package/v3/dist/init/migration/index.d.ts +8 -0
  354. package/v3/dist/init/migration/index.d.ts.map +1 -0
  355. package/v3/dist/init/migration/index.js +8 -0
  356. package/v3/dist/init/migration/index.js.map +1 -0
  357. package/v3/dist/init/orchestrator.d.ts +68 -0
  358. package/v3/dist/init/orchestrator.d.ts.map +1 -0
  359. package/v3/dist/init/orchestrator.js +239 -0
  360. package/v3/dist/init/orchestrator.js.map +1 -0
  361. package/v3/dist/init/phases/01-detection.d.ts +30 -0
  362. package/v3/dist/init/phases/01-detection.d.ts.map +1 -0
  363. package/v3/dist/init/phases/01-detection.js +143 -0
  364. package/v3/dist/init/phases/01-detection.js.map +1 -0
  365. package/v3/dist/init/phases/02-analysis.d.ts +18 -0
  366. package/v3/dist/init/phases/02-analysis.d.ts.map +1 -0
  367. package/v3/dist/init/phases/02-analysis.js +28 -0
  368. package/v3/dist/init/phases/02-analysis.js.map +1 -0
  369. package/v3/dist/init/phases/03-configuration.d.ts +26 -0
  370. package/v3/dist/init/phases/03-configuration.d.ts.map +1 -0
  371. package/v3/dist/init/phases/03-configuration.js +98 -0
  372. package/v3/dist/init/phases/03-configuration.js.map +1 -0
  373. package/v3/dist/init/phases/04-database.d.ts +22 -0
  374. package/v3/dist/init/phases/04-database.d.ts.map +1 -0
  375. package/v3/dist/init/phases/04-database.js +88 -0
  376. package/v3/dist/init/phases/04-database.js.map +1 -0
  377. package/v3/dist/init/phases/05-learning.d.ts +28 -0
  378. package/v3/dist/init/phases/05-learning.d.ts.map +1 -0
  379. package/v3/dist/init/phases/05-learning.js +98 -0
  380. package/v3/dist/init/phases/05-learning.js.map +1 -0
  381. package/v3/dist/init/phases/06-code-intelligence.d.ts +33 -0
  382. package/v3/dist/init/phases/06-code-intelligence.d.ts.map +1 -0
  383. package/v3/dist/init/phases/06-code-intelligence.js +115 -0
  384. package/v3/dist/init/phases/06-code-intelligence.js.map +1 -0
  385. package/v3/dist/init/phases/07-hooks.d.ts +27 -0
  386. package/v3/dist/init/phases/07-hooks.d.ts.map +1 -0
  387. package/v3/dist/init/phases/07-hooks.js +209 -0
  388. package/v3/dist/init/phases/07-hooks.js.map +1 -0
  389. package/v3/dist/init/phases/08-mcp.d.ts +22 -0
  390. package/v3/dist/init/phases/08-mcp.d.ts.map +1 -0
  391. package/v3/dist/init/phases/08-mcp.js +62 -0
  392. package/v3/dist/init/phases/08-mcp.js.map +1 -0
  393. package/v3/dist/init/phases/09-assets.d.ts +23 -0
  394. package/v3/dist/init/phases/09-assets.d.ts.map +1 -0
  395. package/v3/dist/init/phases/09-assets.js +82 -0
  396. package/v3/dist/init/phases/09-assets.js.map +1 -0
  397. package/v3/dist/init/phases/10-workers.d.ts +23 -0
  398. package/v3/dist/init/phases/10-workers.d.ts.map +1 -0
  399. package/v3/dist/init/phases/10-workers.js +111 -0
  400. package/v3/dist/init/phases/10-workers.js.map +1 -0
  401. package/v3/dist/init/phases/11-claude-md.d.ts +26 -0
  402. package/v3/dist/init/phases/11-claude-md.d.ts.map +1 -0
  403. package/v3/dist/init/phases/11-claude-md.js +121 -0
  404. package/v3/dist/init/phases/11-claude-md.js.map +1 -0
  405. package/v3/dist/init/phases/12-verification.d.ts +61 -0
  406. package/v3/dist/init/phases/12-verification.d.ts.map +1 -0
  407. package/v3/dist/init/phases/12-verification.js +370 -0
  408. package/v3/dist/init/phases/12-verification.js.map +1 -0
  409. package/v3/dist/init/phases/index.d.ts +46 -0
  410. package/v3/dist/init/phases/index.d.ts.map +1 -0
  411. package/v3/dist/init/phases/index.js +64 -0
  412. package/v3/dist/init/phases/index.js.map +1 -0
  413. package/v3/dist/init/phases/phase-interface.d.ts +193 -0
  414. package/v3/dist/init/phases/phase-interface.d.ts.map +1 -0
  415. package/v3/dist/init/phases/phase-interface.js +119 -0
  416. package/v3/dist/init/phases/phase-interface.js.map +1 -0
  417. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.d.ts +24 -62
  418. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.d.ts.map +1 -1
  419. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.js +45 -497
  420. package/v3/dist/integrations/agentic-flow/model-router/complexity-analyzer.js.map +1 -1
  421. package/v3/dist/integrations/agentic-flow/model-router/router.js +2 -2
  422. package/v3/dist/integrations/agentic-flow/model-router/router.js.map +1 -1
  423. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.d.ts +98 -0
  424. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.d.ts.map +1 -0
  425. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.js +197 -0
  426. package/v3/dist/integrations/agentic-flow/model-router/score-calculator.js.map +1 -0
  427. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.d.ts +102 -0
  428. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.d.ts.map +1 -0
  429. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.js +372 -0
  430. package/v3/dist/integrations/agentic-flow/model-router/signal-collector.js.map +1 -0
  431. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.d.ts +64 -0
  432. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.d.ts.map +1 -0
  433. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.js +120 -0
  434. package/v3/dist/integrations/agentic-flow/model-router/tier-recommender.js.map +1 -0
  435. package/v3/dist/integrations/coherence/coherence-service.d.ts +323 -0
  436. package/v3/dist/integrations/coherence/coherence-service.d.ts.map +1 -0
  437. package/v3/dist/integrations/coherence/coherence-service.js +856 -0
  438. package/v3/dist/integrations/coherence/coherence-service.js.map +1 -0
  439. package/v3/dist/integrations/coherence/engines/category-adapter.d.ts +170 -0
  440. package/v3/dist/integrations/coherence/engines/category-adapter.d.ts.map +1 -0
  441. package/v3/dist/integrations/coherence/engines/category-adapter.js +403 -0
  442. package/v3/dist/integrations/coherence/engines/category-adapter.js.map +1 -0
  443. package/v3/dist/integrations/coherence/engines/causal-adapter.d.ts +159 -0
  444. package/v3/dist/integrations/coherence/engines/causal-adapter.d.ts.map +1 -0
  445. package/v3/dist/integrations/coherence/engines/causal-adapter.js +348 -0
  446. package/v3/dist/integrations/coherence/engines/causal-adapter.js.map +1 -0
  447. package/v3/dist/integrations/coherence/engines/cohomology-adapter.d.ts +174 -0
  448. package/v3/dist/integrations/coherence/engines/cohomology-adapter.d.ts.map +1 -0
  449. package/v3/dist/integrations/coherence/engines/cohomology-adapter.js +401 -0
  450. package/v3/dist/integrations/coherence/engines/cohomology-adapter.js.map +1 -0
  451. package/v3/dist/integrations/coherence/engines/homotopy-adapter.d.ts +201 -0
  452. package/v3/dist/integrations/coherence/engines/homotopy-adapter.d.ts.map +1 -0
  453. package/v3/dist/integrations/coherence/engines/homotopy-adapter.js +324 -0
  454. package/v3/dist/integrations/coherence/engines/homotopy-adapter.js.map +1 -0
  455. package/v3/dist/integrations/coherence/engines/index.d.ts +20 -0
  456. package/v3/dist/integrations/coherence/engines/index.d.ts.map +1 -0
  457. package/v3/dist/integrations/coherence/engines/index.js +26 -0
  458. package/v3/dist/integrations/coherence/engines/index.js.map +1 -0
  459. package/v3/dist/integrations/coherence/engines/spectral-adapter.d.ts +193 -0
  460. package/v3/dist/integrations/coherence/engines/spectral-adapter.d.ts.map +1 -0
  461. package/v3/dist/integrations/coherence/engines/spectral-adapter.js +565 -0
  462. package/v3/dist/integrations/coherence/engines/spectral-adapter.js.map +1 -0
  463. package/v3/dist/integrations/coherence/engines/witness-adapter.d.ts +175 -0
  464. package/v3/dist/integrations/coherence/engines/witness-adapter.d.ts.map +1 -0
  465. package/v3/dist/integrations/coherence/engines/witness-adapter.js +377 -0
  466. package/v3/dist/integrations/coherence/engines/witness-adapter.js.map +1 -0
  467. package/v3/dist/integrations/coherence/index.d.ts +84 -0
  468. package/v3/dist/integrations/coherence/index.d.ts.map +1 -0
  469. package/v3/dist/integrations/coherence/index.js +114 -0
  470. package/v3/dist/integrations/coherence/index.js.map +1 -0
  471. package/v3/dist/integrations/coherence/threshold-tuner.d.ts +396 -0
  472. package/v3/dist/integrations/coherence/threshold-tuner.d.ts.map +1 -0
  473. package/v3/dist/integrations/coherence/threshold-tuner.js +538 -0
  474. package/v3/dist/integrations/coherence/threshold-tuner.js.map +1 -0
  475. package/v3/dist/integrations/coherence/types.d.ts +879 -0
  476. package/v3/dist/integrations/coherence/types.d.ts.map +1 -0
  477. package/v3/dist/integrations/coherence/types.js +134 -0
  478. package/v3/dist/integrations/coherence/types.js.map +1 -0
  479. package/v3/dist/integrations/coherence/wasm-loader.d.ts +351 -0
  480. package/v3/dist/integrations/coherence/wasm-loader.d.ts.map +1 -0
  481. package/v3/dist/integrations/coherence/wasm-loader.js +842 -0
  482. package/v3/dist/integrations/coherence/wasm-loader.js.map +1 -0
  483. package/v3/dist/integrations/embeddings/index/HNSWIndex.d.ts.map +1 -1
  484. package/v3/dist/integrations/embeddings/index/HNSWIndex.js +4 -1
  485. package/v3/dist/integrations/embeddings/index/HNSWIndex.js.map +1 -1
  486. package/v3/dist/kernel/interfaces.d.ts +8 -1
  487. package/v3/dist/kernel/interfaces.d.ts.map +1 -1
  488. package/v3/dist/learning/aqe-learning-engine.d.ts +272 -0
  489. package/v3/dist/learning/aqe-learning-engine.d.ts.map +1 -0
  490. package/v3/dist/learning/aqe-learning-engine.js +708 -0
  491. package/v3/dist/learning/aqe-learning-engine.js.map +1 -0
  492. package/v3/dist/learning/causal-verifier.d.ts +244 -0
  493. package/v3/dist/learning/causal-verifier.d.ts.map +1 -0
  494. package/v3/dist/learning/causal-verifier.js +300 -0
  495. package/v3/dist/learning/causal-verifier.js.map +1 -0
  496. package/v3/dist/learning/experience-capture.d.ts +266 -0
  497. package/v3/dist/learning/experience-capture.d.ts.map +1 -0
  498. package/v3/dist/learning/experience-capture.js +647 -0
  499. package/v3/dist/learning/experience-capture.js.map +1 -0
  500. package/v3/dist/learning/index.d.ts +8 -0
  501. package/v3/dist/learning/index.d.ts.map +1 -1
  502. package/v3/dist/learning/index.js +16 -0
  503. package/v3/dist/learning/index.js.map +1 -1
  504. package/v3/dist/learning/memory-auditor.d.ts +235 -0
  505. package/v3/dist/learning/memory-auditor.d.ts.map +1 -0
  506. package/v3/dist/learning/memory-auditor.js +480 -0
  507. package/v3/dist/learning/memory-auditor.js.map +1 -0
  508. package/v3/dist/learning/pattern-store.d.ts.map +1 -1
  509. package/v3/dist/learning/pattern-store.js +27 -6
  510. package/v3/dist/learning/pattern-store.js.map +1 -1
  511. package/v3/dist/learning/qe-patterns.d.ts +15 -1
  512. package/v3/dist/learning/qe-patterns.d.ts.map +1 -1
  513. package/v3/dist/learning/qe-patterns.js +26 -5
  514. package/v3/dist/learning/qe-patterns.js.map +1 -1
  515. package/v3/dist/learning/qe-reasoning-bank.d.ts +38 -2
  516. package/v3/dist/learning/qe-reasoning-bank.d.ts.map +1 -1
  517. package/v3/dist/learning/qe-reasoning-bank.js +86 -4
  518. package/v3/dist/learning/qe-reasoning-bank.js.map +1 -1
  519. package/v3/dist/learning/real-qe-reasoning-bank.d.ts +32 -2
  520. package/v3/dist/learning/real-qe-reasoning-bank.d.ts.map +1 -1
  521. package/v3/dist/learning/real-qe-reasoning-bank.js +61 -6
  522. package/v3/dist/learning/real-qe-reasoning-bank.js.map +1 -1
  523. package/v3/dist/mcp/bundle.js +8786 -1737
  524. package/v3/dist/mcp/security/cve-prevention.d.ts +31 -134
  525. package/v3/dist/mcp/security/cve-prevention.d.ts.map +1 -1
  526. package/v3/dist/mcp/security/cve-prevention.js +37 -562
  527. package/v3/dist/mcp/security/cve-prevention.js.map +1 -1
  528. package/v3/dist/mcp/security/index.d.ts +5 -1
  529. package/v3/dist/mcp/security/index.d.ts.map +1 -1
  530. package/v3/dist/mcp/security/validators/command-validator.d.ts +41 -0
  531. package/v3/dist/mcp/security/validators/command-validator.d.ts.map +1 -0
  532. package/v3/dist/mcp/security/validators/command-validator.js +123 -0
  533. package/v3/dist/mcp/security/validators/command-validator.js.map +1 -0
  534. package/v3/dist/mcp/security/validators/crypto-validator.d.ts +40 -0
  535. package/v3/dist/mcp/security/validators/crypto-validator.d.ts.map +1 -0
  536. package/v3/dist/mcp/security/validators/crypto-validator.js +72 -0
  537. package/v3/dist/mcp/security/validators/crypto-validator.js.map +1 -0
  538. package/v3/dist/mcp/security/validators/index.d.ts +12 -0
  539. package/v3/dist/mcp/security/validators/index.d.ts.map +1 -0
  540. package/v3/dist/mcp/security/validators/index.js +22 -0
  541. package/v3/dist/mcp/security/validators/index.js.map +1 -0
  542. package/v3/dist/mcp/security/validators/input-sanitizer.d.ts +56 -0
  543. package/v3/dist/mcp/security/validators/input-sanitizer.d.ts.map +1 -0
  544. package/v3/dist/mcp/security/validators/input-sanitizer.js +157 -0
  545. package/v3/dist/mcp/security/validators/input-sanitizer.js.map +1 -0
  546. package/v3/dist/mcp/security/validators/interfaces.d.ts +164 -0
  547. package/v3/dist/mcp/security/validators/interfaces.d.ts.map +1 -0
  548. package/v3/dist/mcp/security/validators/interfaces.js +6 -0
  549. package/v3/dist/mcp/security/validators/interfaces.js.map +1 -0
  550. package/v3/dist/mcp/security/validators/path-traversal-validator.d.ts +50 -0
  551. package/v3/dist/mcp/security/validators/path-traversal-validator.d.ts.map +1 -0
  552. package/v3/dist/mcp/security/validators/path-traversal-validator.js +242 -0
  553. package/v3/dist/mcp/security/validators/path-traversal-validator.js.map +1 -0
  554. package/v3/dist/mcp/security/validators/regex-safety-validator.d.ts +50 -0
  555. package/v3/dist/mcp/security/validators/regex-safety-validator.d.ts.map +1 -0
  556. package/v3/dist/mcp/security/validators/regex-safety-validator.js +183 -0
  557. package/v3/dist/mcp/security/validators/regex-safety-validator.js.map +1 -0
  558. package/v3/dist/mcp/security/validators/validation-orchestrator.d.ts +66 -0
  559. package/v3/dist/mcp/security/validators/validation-orchestrator.d.ts.map +1 -0
  560. package/v3/dist/mcp/security/validators/validation-orchestrator.js +146 -0
  561. package/v3/dist/mcp/security/validators/validation-orchestrator.js.map +1 -0
  562. package/v3/dist/mcp/server.d.ts.map +1 -1
  563. package/v3/dist/mcp/server.js +1 -0
  564. package/v3/dist/mcp/server.js.map +1 -1
  565. package/v3/dist/mcp/tool-registry.d.ts +3 -1
  566. package/v3/dist/mcp/tool-registry.d.ts.map +1 -1
  567. package/v3/dist/mcp/tool-registry.js +155 -2
  568. package/v3/dist/mcp/tool-registry.js.map +1 -1
  569. package/v3/dist/mcp/tools/coherence/audit.d.ts +107 -0
  570. package/v3/dist/mcp/tools/coherence/audit.d.ts.map +1 -0
  571. package/v3/dist/mcp/tools/coherence/audit.js +236 -0
  572. package/v3/dist/mcp/tools/coherence/audit.js.map +1 -0
  573. package/v3/dist/mcp/tools/coherence/check.d.ts +106 -0
  574. package/v3/dist/mcp/tools/coherence/check.d.ts.map +1 -0
  575. package/v3/dist/mcp/tools/coherence/check.js +205 -0
  576. package/v3/dist/mcp/tools/coherence/check.js.map +1 -0
  577. package/v3/dist/mcp/tools/coherence/collapse.d.ts +123 -0
  578. package/v3/dist/mcp/tools/coherence/collapse.d.ts.map +1 -0
  579. package/v3/dist/mcp/tools/coherence/collapse.js +279 -0
  580. package/v3/dist/mcp/tools/coherence/collapse.js.map +1 -0
  581. package/v3/dist/mcp/tools/coherence/consensus.d.ts +100 -0
  582. package/v3/dist/mcp/tools/coherence/consensus.d.ts.map +1 -0
  583. package/v3/dist/mcp/tools/coherence/consensus.js +201 -0
  584. package/v3/dist/mcp/tools/coherence/consensus.js.map +1 -0
  585. package/v3/dist/mcp/tools/coherence/index.d.ts +31 -0
  586. package/v3/dist/mcp/tools/coherence/index.d.ts.map +1 -0
  587. package/v3/dist/mcp/tools/coherence/index.js +42 -0
  588. package/v3/dist/mcp/tools/coherence/index.js.map +1 -0
  589. package/v3/dist/mcp/tools/index.d.ts +6 -1
  590. package/v3/dist/mcp/tools/index.d.ts.map +1 -1
  591. package/v3/dist/mcp/tools/index.js +9 -1
  592. package/v3/dist/mcp/tools/index.js.map +1 -1
  593. package/v3/dist/mcp/tools/mincut/index.d.ts +1 -1
  594. package/v3/dist/mcp/tools/mincut/index.d.ts.map +1 -1
  595. package/v3/dist/mcp/tools/mincut/index.js.map +1 -1
  596. package/v3/dist/mcp/tools/registry.d.ts +4 -0
  597. package/v3/dist/mcp/tools/registry.d.ts.map +1 -1
  598. package/v3/dist/mcp/tools/registry.js +5 -0
  599. package/v3/dist/mcp/tools/registry.js.map +1 -1
  600. package/v3/dist/mcp/tools/test-generation/generate.d.ts +1 -0
  601. package/v3/dist/mcp/tools/test-generation/generate.d.ts.map +1 -1
  602. package/v3/dist/mcp/tools/test-generation/generate.js +3 -2
  603. package/v3/dist/mcp/tools/test-generation/generate.js.map +1 -1
  604. package/v3/dist/mcp/types.d.ts +1 -1
  605. package/v3/dist/mcp/types.d.ts.map +1 -1
  606. package/v3/dist/strange-loop/belief-reconciler.d.ts +357 -0
  607. package/v3/dist/strange-loop/belief-reconciler.d.ts.map +1 -0
  608. package/v3/dist/strange-loop/belief-reconciler.js +696 -0
  609. package/v3/dist/strange-loop/belief-reconciler.js.map +1 -0
  610. package/v3/dist/strange-loop/index.d.ts +1 -0
  611. package/v3/dist/strange-loop/index.d.ts.map +1 -1
  612. package/v3/dist/strange-loop/index.js +2 -0
  613. package/v3/dist/strange-loop/index.js.map +1 -1
  614. package/v3/dist/strange-loop/strange-loop.d.ts +177 -5
  615. package/v3/dist/strange-loop/strange-loop.d.ts.map +1 -1
  616. package/v3/dist/strange-loop/strange-loop.js +452 -9
  617. package/v3/dist/strange-loop/strange-loop.js.map +1 -1
  618. package/v3/dist/strange-loop/types.d.ts +205 -1
  619. package/v3/dist/strange-loop/types.d.ts.map +1 -1
  620. package/v3/dist/strange-loop/types.js +5 -0
  621. package/v3/dist/strange-loop/types.js.map +1 -1
  622. package/v3/dist/sync/cloud/index.d.ts +8 -0
  623. package/v3/dist/sync/cloud/index.d.ts.map +1 -0
  624. package/v3/dist/sync/cloud/index.js +8 -0
  625. package/v3/dist/sync/cloud/index.js.map +1 -0
  626. package/v3/dist/sync/cloud/postgres-writer.d.ts +88 -0
  627. package/v3/dist/sync/cloud/postgres-writer.d.ts.map +1 -0
  628. package/v3/dist/sync/cloud/postgres-writer.js +319 -0
  629. package/v3/dist/sync/cloud/postgres-writer.js.map +1 -0
  630. package/v3/dist/sync/cloud/tunnel-manager.d.ts +75 -0
  631. package/v3/dist/sync/cloud/tunnel-manager.d.ts.map +1 -0
  632. package/v3/dist/sync/cloud/tunnel-manager.js +221 -0
  633. package/v3/dist/sync/cloud/tunnel-manager.js.map +1 -0
  634. package/v3/dist/sync/index.d.ts +35 -0
  635. package/v3/dist/sync/index.d.ts.map +1 -0
  636. package/v3/dist/sync/index.js +35 -0
  637. package/v3/dist/sync/index.js.map +1 -0
  638. package/v3/dist/sync/interfaces.d.ts +245 -0
  639. package/v3/dist/sync/interfaces.d.ts.map +1 -0
  640. package/v3/dist/sync/interfaces.js +160 -0
  641. package/v3/dist/sync/interfaces.js.map +1 -0
  642. package/v3/dist/sync/readers/index.d.ts +8 -0
  643. package/v3/dist/sync/readers/index.d.ts.map +1 -0
  644. package/v3/dist/sync/readers/index.js +8 -0
  645. package/v3/dist/sync/readers/index.js.map +1 -0
  646. package/v3/dist/sync/readers/json-reader.d.ts +95 -0
  647. package/v3/dist/sync/readers/json-reader.d.ts.map +1 -0
  648. package/v3/dist/sync/readers/json-reader.js +306 -0
  649. package/v3/dist/sync/readers/json-reader.js.map +1 -0
  650. package/v3/dist/sync/readers/sqlite-reader.d.ts +88 -0
  651. package/v3/dist/sync/readers/sqlite-reader.d.ts.map +1 -0
  652. package/v3/dist/sync/readers/sqlite-reader.js +255 -0
  653. package/v3/dist/sync/readers/sqlite-reader.js.map +1 -0
  654. package/v3/dist/sync/sync-agent.d.ts +116 -0
  655. package/v3/dist/sync/sync-agent.d.ts.map +1 -0
  656. package/v3/dist/sync/sync-agent.js +416 -0
  657. package/v3/dist/sync/sync-agent.js.map +1 -0
  658. package/v3/package.json +17 -2
@@ -2,32 +2,46 @@
2
2
  * Agentic QE v3 - Test Generation Service
3
3
  * Implements ITestGenerationService for AI-powered test generation
4
4
  *
5
- * Uses @faker-js/faker for realistic test data generation
5
+ * Uses Strategy Pattern generators for framework-specific code generation
6
6
  * Uses TypeScript AST parser for code analysis
7
+ * Delegates to specialized services for TDD, property tests, and test data
7
8
  */
8
9
  import { v4 as uuidv4 } from 'uuid';
9
10
  import * as fs from 'fs';
10
11
  import * as path from 'path';
11
12
  import * as ts from 'typescript';
12
- import { faker } from '@faker-js/faker';
13
13
  import { ok, err } from '../../../shared/types';
14
+ import { TestGeneratorFactory } from '../factories/test-generator-factory';
15
+ import { TDDGeneratorService } from './tdd-generator';
16
+ import { PropertyTestGeneratorService } from './property-test-generator';
17
+ import { TestDataGeneratorService } from './test-data-generator';
14
18
  const DEFAULT_CONFIG = {
15
- defaultFramework: 'jest',
19
+ defaultFramework: 'vitest',
16
20
  maxTestsPerFile: 50,
17
21
  coverageTargetDefault: 80,
18
22
  enableAIGeneration: true,
19
23
  };
20
24
  /**
21
25
  * Test Generation Service Implementation
22
- * Uses heuristic analysis and AST parsing to generate test cases from source code
23
- * Supports TDD workflow, property-based testing, and pattern-aware generation
26
+ * Uses Strategy Pattern generators for framework-specific test generation
27
+ * Delegates TDD, property testing, and test data to specialized services
28
+ *
29
+ * ADR-XXX: Refactored to use Dependency Injection for better testability and flexibility
24
30
  */
25
31
  export class TestGeneratorService {
26
- memory;
27
32
  config;
28
- constructor(memory, config = {}) {
29
- this.memory = memory;
33
+ memory;
34
+ generatorFactory;
35
+ tddGenerator;
36
+ propertyTestGenerator;
37
+ testDataGenerator;
38
+ constructor(dependencies, config = {}) {
30
39
  this.config = { ...DEFAULT_CONFIG, ...config };
40
+ this.memory = dependencies.memory;
41
+ this.generatorFactory = dependencies.generatorFactory || new TestGeneratorFactory();
42
+ this.tddGenerator = dependencies.tddGenerator || new TDDGeneratorService();
43
+ this.propertyTestGenerator = dependencies.propertyTestGenerator || new PropertyTestGeneratorService();
44
+ this.testDataGenerator = dependencies.testDataGenerator || new TestDataGeneratorService();
31
45
  }
32
46
  /**
33
47
  * Generate tests for given source files
@@ -40,7 +54,6 @@ export class TestGeneratorService {
40
54
  }
41
55
  const tests = [];
42
56
  const patternsUsed = [];
43
- // Process each source file
44
57
  for (const sourceFile of sourceFiles) {
45
58
  const fileTests = await this.generateTestsForFile(sourceFile, testType, framework, patterns);
46
59
  if (fileTests.success) {
@@ -48,14 +61,12 @@ export class TestGeneratorService {
48
61
  patternsUsed.push(...fileTests.value.patternsUsed);
49
62
  }
50
63
  }
51
- // Calculate coverage estimate based on test count and complexity
52
64
  const coverageEstimate = this.estimateCoverage(tests, coverageTarget);
53
- // Store generation metadata in memory
54
65
  await this.storeGenerationMetadata(tests, patternsUsed);
55
66
  return ok({
56
67
  tests,
57
68
  coverageEstimate,
58
- patternsUsed: [...new Set(patternsUsed)],
69
+ patternsUsed: Array.from(new Set(patternsUsed)),
59
70
  });
60
71
  }
61
72
  catch (error) {
@@ -70,13 +81,13 @@ export class TestGeneratorService {
70
81
  if (uncoveredLines.length === 0) {
71
82
  return ok([]);
72
83
  }
73
- // Analyze uncovered lines and generate targeted tests
74
- // Groups consecutive lines and generates tests for each block
75
84
  const tests = [];
76
- // Group uncovered lines into logical blocks
77
85
  const lineGroups = this.groupConsecutiveLines(uncoveredLines);
86
+ const frameworkType = this.generatorFactory.supports(framework)
87
+ ? framework
88
+ : this.config.defaultFramework;
78
89
  for (const group of lineGroups) {
79
- const test = await this.generateTestForLines(file, group, framework);
90
+ const test = await this.generateTestForLines(file, group, frameworkType);
80
91
  if (test) {
81
92
  tests.push(test);
82
93
  }
@@ -88,87 +99,49 @@ export class TestGeneratorService {
88
99
  }
89
100
  }
90
101
  /**
91
- * Generate tests following TDD workflow
102
+ * Generate tests following TDD workflow - delegates to TDDGeneratorService
92
103
  */
93
104
  async generateTDDTests(request) {
94
105
  try {
95
- const { feature, behavior, framework, phase } = request;
96
- switch (phase) {
97
- case 'red':
98
- // Generate failing test first
99
- return ok(await this.generateRedPhaseTest(feature, behavior, framework));
100
- case 'green':
101
- // Generate minimal implementation to make test pass
102
- return ok(await this.generateGreenPhaseCode(feature, behavior, framework));
103
- case 'refactor':
104
- // Suggest refactoring improvements
105
- return ok(await this.generateRefactoringSuggestions(feature, behavior));
106
- default:
107
- return err(new Error(`Unknown TDD phase: ${phase}`));
108
- }
106
+ const result = await this.tddGenerator.generateTDDTests(request);
107
+ return ok(result);
109
108
  }
110
109
  catch (error) {
111
110
  return err(error instanceof Error ? error : new Error(String(error)));
112
111
  }
113
112
  }
114
113
  /**
115
- * Generate property-based tests
114
+ * Generate property-based tests - delegates to PropertyTestGeneratorService
116
115
  */
117
116
  async generatePropertyTests(request) {
118
117
  try {
119
- const { function: funcName, properties, constraints = {} } = request;
120
- // Generate property-based tests using fast-check generators
121
- const tests = properties.map((property) => ({
122
- property,
123
- testCode: this.generatePropertyTestCode(funcName, property, constraints),
124
- generators: this.inferGenerators(property, constraints),
125
- }));
126
- return ok({
127
- tests,
128
- arbitraries: this.collectArbitraries(tests),
129
- });
118
+ const result = await this.propertyTestGenerator.generatePropertyTests(request);
119
+ return ok(result);
130
120
  }
131
121
  catch (error) {
132
122
  return err(error instanceof Error ? error : new Error(String(error)));
133
123
  }
134
124
  }
135
125
  /**
136
- * Generate test data based on schema
126
+ * Generate test data based on schema - delegates to TestDataGeneratorService
137
127
  */
138
128
  async generateTestData(request) {
139
129
  try {
140
- const { schema, count, locale = 'en', preserveRelationships = false } = request;
141
- // Generate test data using @faker-js/faker with seeded randomness
142
- const seed = Date.now();
143
- const records = [];
144
- for (let i = 0; i < count; i++) {
145
- const record = this.generateRecordFromSchema(schema, seed + i, locale);
146
- records.push(record);
147
- }
148
- // Handle relationships if needed
149
- if (preserveRelationships) {
150
- this.linkRelatedRecords(records, schema);
151
- }
152
- return ok({
153
- records,
154
- schema,
155
- seed,
156
- });
130
+ const result = await this.testDataGenerator.generateTestData(request);
131
+ return ok(result);
157
132
  }
158
133
  catch (error) {
159
134
  return err(error instanceof Error ? error : new Error(String(error)));
160
135
  }
161
136
  }
162
137
  // ============================================================================
163
- // Private Helper Methods
138
+ // Private Helper Methods - Core Test Generation
164
139
  // ============================================================================
165
140
  async generateTestsForFile(sourceFile, testType, framework, patterns) {
166
141
  const testFile = this.getTestFilePath(sourceFile, framework);
167
142
  const patternsUsed = [];
168
- // Look for applicable patterns from memory
169
143
  const applicablePatterns = await this.findApplicablePatterns(sourceFile, patterns);
170
144
  patternsUsed.push(...applicablePatterns.map((p) => p.name));
171
- // Try to read and parse the source file for real AST analysis
172
145
  let codeAnalysis = null;
173
146
  try {
174
147
  const content = fs.readFileSync(sourceFile, 'utf-8');
@@ -177,17 +150,20 @@ export class TestGeneratorService {
177
150
  catch {
178
151
  // File doesn't exist or can't be read - use stub generation
179
152
  }
180
- // Generate test code based on analysis or fall back to stub
181
- let testCode;
182
- if (codeAnalysis && (codeAnalysis.functions.length > 0 || codeAnalysis.classes.length > 0)) {
183
- testCode = this.generateRealTestCode(sourceFile, testType, framework, codeAnalysis, applicablePatterns);
184
- }
185
- else {
186
- testCode = this.generateStubTestCode(sourceFile, testType, framework, applicablePatterns);
187
- }
153
+ const generator = this.generatorFactory.create(framework);
154
+ const moduleName = this.extractModuleName(sourceFile);
155
+ const importPath = this.getImportPath(sourceFile);
156
+ const context = {
157
+ moduleName,
158
+ importPath,
159
+ testType,
160
+ patterns: applicablePatterns,
161
+ analysis: codeAnalysis ?? undefined,
162
+ };
163
+ const testCode = generator.generateTests(context);
188
164
  const test = {
189
165
  id: uuidv4(),
190
- name: `${this.extractModuleName(sourceFile)} tests`,
166
+ name: `${moduleName} tests`,
191
167
  sourceFile,
192
168
  testFile,
193
169
  testCode,
@@ -196,19 +172,36 @@ export class TestGeneratorService {
196
172
  };
197
173
  return ok({ tests: [test], patternsUsed });
198
174
  }
199
- /**
200
- * Analyze source code using TypeScript AST
201
- */
175
+ async generateTestForLines(file, lines, framework) {
176
+ if (lines.length === 0)
177
+ return null;
178
+ const testId = uuidv4();
179
+ const testFile = this.getTestFilePath(file, framework);
180
+ const moduleName = this.extractModuleName(file);
181
+ const importPath = this.getImportPath(file);
182
+ const generator = this.generatorFactory.create(framework);
183
+ const testCode = generator.generateCoverageTests(moduleName, importPath, lines);
184
+ return {
185
+ id: testId,
186
+ name: `Coverage test for lines ${lines[0]}-${lines[lines.length - 1]}`,
187
+ sourceFile: file,
188
+ testFile,
189
+ testCode,
190
+ type: 'unit',
191
+ assertions: this.countAssertions(testCode),
192
+ };
193
+ }
194
+ // ============================================================================
195
+ // Private Helper Methods - AST Analysis
196
+ // ============================================================================
202
197
  analyzeSourceCode(content, fileName) {
203
198
  const sourceFile = ts.createSourceFile(path.basename(fileName), content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
204
199
  const functions = [];
205
200
  const classes = [];
206
201
  const visit = (node) => {
207
- // Extract function declarations
208
202
  if (ts.isFunctionDeclaration(node) && node.name) {
209
203
  functions.push(this.extractFunctionInfo(node, sourceFile));
210
204
  }
211
- // Extract arrow functions assigned to variables
212
205
  else if (ts.isVariableStatement(node)) {
213
206
  for (const declaration of node.declarationList.declarations) {
214
207
  if (ts.isVariableDeclaration(declaration) &&
@@ -220,7 +213,6 @@ export class TestGeneratorService {
220
213
  }
221
214
  }
222
215
  }
223
- // Extract class declarations
224
216
  else if (ts.isClassDeclaration(node) && node.name) {
225
217
  classes.push(this.extractClassInfo(node, sourceFile));
226
218
  }
@@ -229,9 +221,6 @@ export class TestGeneratorService {
229
221
  ts.forEachChild(sourceFile, visit);
230
222
  return { functions, classes };
231
223
  }
232
- /**
233
- * Extract function information from AST
234
- */
235
224
  extractFunctionInfo(node, sourceFile) {
236
225
  const name = node.name?.getText(sourceFile) || 'anonymous';
237
226
  const parameters = this.extractParameters(node.parameters, sourceFile);
@@ -252,9 +241,6 @@ export class TestGeneratorService {
252
241
  body: node.body?.getText(sourceFile),
253
242
  };
254
243
  }
255
- /**
256
- * Extract arrow function information from AST
257
- */
258
244
  extractArrowFunctionInfo(name, node, sourceFile, parentNode) {
259
245
  const parameters = this.extractParameters(node.parameters, sourceFile);
260
246
  const returnType = node.type?.getText(sourceFile);
@@ -275,9 +261,6 @@ export class TestGeneratorService {
275
261
  body: node.body?.getText(sourceFile),
276
262
  };
277
263
  }
278
- /**
279
- * Extract class information from AST
280
- */
281
264
  extractClassInfo(node, sourceFile) {
282
265
  const name = node.name?.getText(sourceFile) || 'AnonymousClass';
283
266
  const methods = [];
@@ -331,9 +314,6 @@ export class TestGeneratorService {
331
314
  constructorParams,
332
315
  };
333
316
  }
334
- /**
335
- * Extract parameters from a function
336
- */
337
317
  extractParameters(params, sourceFile) {
338
318
  return params.map((param) => ({
339
319
  name: param.name.getText(sourceFile),
@@ -342,9 +322,6 @@ export class TestGeneratorService {
342
322
  defaultValue: param.initializer?.getText(sourceFile),
343
323
  }));
344
324
  }
345
- /**
346
- * Calculate cyclomatic complexity of a node
347
- */
348
325
  calculateComplexity(node) {
349
326
  let complexity = 1;
350
327
  const visit = (n) => {
@@ -374,452 +351,17 @@ export class TestGeneratorService {
374
351
  ts.forEachChild(node, visit);
375
352
  return complexity;
376
353
  }
377
- /**
378
- * Generate real test code based on AST analysis
379
- */
380
- generateRealTestCode(sourceFile, testType, framework, analysis, patterns) {
381
- const moduleName = this.extractModuleName(sourceFile);
382
- const importPath = this.getImportPath(sourceFile);
383
- switch (framework) {
384
- case 'jest':
385
- case 'vitest':
386
- return this.generateRealJestVitestTest(moduleName, importPath, testType, analysis, patterns, framework);
387
- case 'mocha':
388
- return this.generateRealMochaTest(moduleName, importPath, testType, analysis, patterns);
389
- case 'pytest':
390
- return this.generateRealPytestTest(moduleName, importPath, testType, analysis, patterns);
391
- default:
392
- return this.generateRealJestVitestTest(moduleName, importPath, testType, analysis, patterns, 'vitest');
393
- }
394
- }
395
- /**
396
- * Generate real Jest/Vitest test code
397
- */
398
- generateRealJestVitestTest(moduleName, importPath, testType, analysis, patterns, framework) {
399
- const patternComment = patterns.length > 0
400
- ? `// Applied patterns: ${patterns.map((p) => p.name).join(', ')}\n`
401
- : '';
402
- // Collect all exports to import
403
- const exports = [];
404
- for (const fn of analysis.functions) {
405
- if (fn.isExported)
406
- exports.push(fn.name);
407
- }
408
- for (const cls of analysis.classes) {
409
- if (cls.isExported)
410
- exports.push(cls.name);
411
- }
412
- const importStatement = exports.length > 0
413
- ? `import { ${exports.join(', ')} } from '${importPath}';`
414
- : `import * as ${moduleName} from '${importPath}';`;
415
- let testCode = `${patternComment}import { describe, it, expect, beforeEach${framework === 'vitest' ? ', vi' : ''} } from '${framework}';
416
- ${importStatement}
417
-
418
- `;
419
- // Generate tests for each function
420
- for (const fn of analysis.functions) {
421
- testCode += this.generateFunctionTests(fn, testType);
422
- }
423
- // Generate tests for each class
424
- for (const cls of analysis.classes) {
425
- testCode += this.generateClassTests(cls, testType);
426
- }
427
- return testCode;
428
- }
429
- /**
430
- * Generate tests for a function
431
- */
432
- generateFunctionTests(fn, _testType) {
433
- const testCases = this.generateTestCasesForFunction(fn);
434
- let code = `describe('${fn.name}', () => {\n`;
435
- for (const testCase of testCases) {
436
- if (testCase.setup) {
437
- code += ` ${testCase.setup}\n\n`;
438
- }
439
- const asyncPrefix = fn.isAsync ? 'async ' : '';
440
- code += ` it('${testCase.description}', ${asyncPrefix}() => {\n`;
441
- code += ` ${testCase.action}\n`;
442
- code += ` ${testCase.assertion}\n`;
443
- code += ` });\n\n`;
444
- }
445
- code += `});\n\n`;
446
- return code;
447
- }
448
- /**
449
- * Generate test cases for a function
450
- */
451
- generateTestCasesForFunction(fn) {
452
- const testCases = [];
453
- // Generate valid input test
454
- const validParams = fn.parameters.map((p) => this.generateTestValue(p)).join(', ');
455
- const fnCall = fn.isAsync ? `await ${fn.name}(${validParams})` : `${fn.name}(${validParams})`;
456
- testCases.push({
457
- description: 'should handle valid input correctly',
458
- type: 'happy-path',
459
- action: `const result = ${fnCall};`,
460
- assertion: 'expect(result).toBeDefined();',
461
- });
462
- // Generate tests for each parameter
463
- for (const param of fn.parameters) {
464
- if (!param.optional) {
465
- // Test with undefined
466
- const paramsWithUndefined = fn.parameters
467
- .map((p) => (p.name === param.name ? 'undefined' : this.generateTestValue(p)))
468
- .join(', ');
469
- testCases.push({
470
- description: `should handle undefined ${param.name}`,
471
- type: 'error-handling',
472
- action: fn.isAsync
473
- ? `const action = async () => await ${fn.name}(${paramsWithUndefined});`
474
- : `const action = () => ${fn.name}(${paramsWithUndefined});`,
475
- assertion: 'expect(action).toThrow();',
476
- });
477
- }
478
- // Type-specific boundary tests
479
- if (param.type?.includes('string')) {
480
- const paramsWithEmpty = fn.parameters
481
- .map((p) => (p.name === param.name ? "''" : this.generateTestValue(p)))
482
- .join(', ');
483
- const emptyCall = fn.isAsync
484
- ? `await ${fn.name}(${paramsWithEmpty})`
485
- : `${fn.name}(${paramsWithEmpty})`;
486
- testCases.push({
487
- description: `should handle empty string for ${param.name}`,
488
- type: 'boundary',
489
- action: `const result = ${emptyCall};`,
490
- assertion: 'expect(result).toBeDefined();',
491
- });
492
- }
493
- if (param.type?.includes('number')) {
494
- const paramsWithZero = fn.parameters
495
- .map((p) => (p.name === param.name ? '0' : this.generateTestValue(p)))
496
- .join(', ');
497
- const zeroCall = fn.isAsync
498
- ? `await ${fn.name}(${paramsWithZero})`
499
- : `${fn.name}(${paramsWithZero})`;
500
- testCases.push({
501
- description: `should handle zero for ${param.name}`,
502
- type: 'boundary',
503
- action: `const result = ${zeroCall};`,
504
- assertion: 'expect(result).toBeDefined();',
505
- });
506
- const paramsWithNegative = fn.parameters
507
- .map((p) => (p.name === param.name ? '-1' : this.generateTestValue(p)))
508
- .join(', ');
509
- const negativeCall = fn.isAsync
510
- ? `await ${fn.name}(${paramsWithNegative})`
511
- : `${fn.name}(${paramsWithNegative})`;
512
- testCases.push({
513
- description: `should handle negative value for ${param.name}`,
514
- type: 'edge-case',
515
- action: `const result = ${negativeCall};`,
516
- assertion: 'expect(result).toBeDefined();',
517
- });
518
- }
519
- if (param.type?.includes('[]') || param.type?.includes('Array')) {
520
- const paramsWithEmpty = fn.parameters
521
- .map((p) => (p.name === param.name ? '[]' : this.generateTestValue(p)))
522
- .join(', ');
523
- const emptyCall = fn.isAsync
524
- ? `await ${fn.name}(${paramsWithEmpty})`
525
- : `${fn.name}(${paramsWithEmpty})`;
526
- testCases.push({
527
- description: `should handle empty array for ${param.name}`,
528
- type: 'boundary',
529
- action: `const result = ${emptyCall};`,
530
- assertion: 'expect(result).toBeDefined();',
531
- });
532
- }
533
- }
534
- // Async rejection test
535
- if (fn.isAsync) {
536
- testCases.push({
537
- description: 'should handle async rejection gracefully',
538
- type: 'error-handling',
539
- action: `// Mock or setup to cause rejection`,
540
- assertion: `// await expect(${fn.name}(invalidParams)).rejects.toThrow();`,
541
- });
542
- }
543
- return testCases;
544
- }
545
- /**
546
- * Generate tests for a class
547
- */
548
- generateClassTests(cls, testType) {
549
- let code = `describe('${cls.name}', () => {\n`;
550
- code += ` let instance: ${cls.name};\n\n`;
551
- // Setup
552
- if (cls.hasConstructor && cls.constructorParams) {
553
- const constructorArgs = cls.constructorParams
554
- .map((p) => this.generateTestValue(p))
555
- .join(', ');
556
- code += ` beforeEach(() => {\n`;
557
- code += ` instance = new ${cls.name}(${constructorArgs});\n`;
558
- code += ` });\n\n`;
559
- }
560
- else {
561
- code += ` beforeEach(() => {\n`;
562
- code += ` instance = new ${cls.name}();\n`;
563
- code += ` });\n\n`;
564
- }
565
- // Constructor test
566
- code += ` it('should instantiate correctly', () => {\n`;
567
- code += ` expect(instance).toBeInstanceOf(${cls.name});\n`;
568
- code += ` });\n\n`;
569
- // Generate tests for each public method
570
- for (const method of cls.methods) {
571
- if (!method.name.startsWith('_') && !method.name.startsWith('#')) {
572
- code += this.generateMethodTests(method, cls.name, testType);
573
- }
574
- }
575
- code += `});\n\n`;
576
- return code;
577
- }
578
- /**
579
- * Generate tests for a class method
580
- */
581
- generateMethodTests(method, _className, _testType) {
582
- let code = ` describe('${method.name}', () => {\n`;
583
- const validParams = method.parameters.map((p) => this.generateTestValue(p)).join(', ');
584
- const methodCall = method.isAsync
585
- ? `await instance.${method.name}(${validParams})`
586
- : `instance.${method.name}(${validParams})`;
587
- // Happy path
588
- const asyncPrefix = method.isAsync ? 'async ' : '';
589
- code += ` it('should execute successfully', ${asyncPrefix}() => {\n`;
590
- code += ` const result = ${methodCall};\n`;
591
- code += ` expect(result).toBeDefined();\n`;
592
- code += ` });\n`;
593
- // Error handling for non-optional params
594
- for (const param of method.parameters) {
595
- if (!param.optional) {
596
- const paramsWithUndefined = method.parameters
597
- .map((p) => (p.name === param.name ? 'undefined as any' : this.generateTestValue(p)))
598
- .join(', ');
599
- code += `\n it('should handle invalid ${param.name}', () => {\n`;
600
- code += ` expect(() => instance.${method.name}(${paramsWithUndefined})).toThrow();\n`;
601
- code += ` });\n`;
602
- }
603
- }
604
- code += ` });\n\n`;
605
- return code;
606
- }
607
- /**
608
- * Generate a test value for a parameter
609
- */
610
- generateTestValue(param) {
611
- if (param.defaultValue) {
612
- return param.defaultValue;
613
- }
614
- const type = param.type?.toLowerCase() || 'unknown';
615
- const name = param.name.toLowerCase();
616
- // Infer from param name first
617
- if (name.includes('id'))
618
- return `'${faker.string.uuid()}'`;
619
- if (name.includes('email'))
620
- return `'${faker.internet.email()}'`;
621
- if (name.includes('name'))
622
- return `'${faker.person.fullName()}'`;
623
- if (name.includes('url'))
624
- return `'${faker.internet.url()}'`;
625
- if (name.includes('date'))
626
- return `new Date('${faker.date.recent().toISOString()}')`;
627
- // Then by type
628
- if (type.includes('string'))
629
- return `'${faker.lorem.word()}'`;
630
- if (type.includes('number'))
631
- return String(faker.number.int({ min: 1, max: 100 }));
632
- if (type.includes('boolean'))
633
- return 'true';
634
- if (type.includes('[]') || type.includes('array'))
635
- return '[]';
636
- if (type.includes('object') || type.includes('{'))
637
- return '{}';
638
- if (type.includes('function'))
639
- return '() => {}';
640
- if (type.includes('promise'))
641
- return 'Promise.resolve()';
642
- if (type.includes('date'))
643
- return 'new Date()';
644
- // Default
645
- return `mock${param.name.charAt(0).toUpperCase() + param.name.slice(1)}`;
646
- }
647
- /**
648
- * Generate real Mocha test code
649
- */
650
- generateRealMochaTest(moduleName, importPath, testType, analysis, patterns) {
651
- const patternComment = patterns.length > 0
652
- ? `// Applied patterns: ${patterns.map((p) => p.name).join(', ')}\n`
653
- : '';
654
- const exports = [];
655
- for (const fn of analysis.functions) {
656
- if (fn.isExported)
657
- exports.push(fn.name);
658
- }
659
- for (const cls of analysis.classes) {
660
- if (cls.isExported)
661
- exports.push(cls.name);
662
- }
663
- const importStatement = exports.length > 0
664
- ? `import { ${exports.join(', ')} } from '${importPath}';`
665
- : `import * as ${moduleName} from '${importPath}';`;
666
- let code = `${patternComment}import { expect } from 'chai';
667
- ${importStatement}
668
-
669
- describe('${moduleName} - ${testType} tests', function() {
670
- `;
671
- for (const fn of analysis.functions) {
672
- code += this.generateMochaFunctionTests(fn);
673
- }
674
- for (const cls of analysis.classes) {
675
- code += this.generateMochaClassTests(cls);
676
- }
677
- code += `});\n`;
678
- return code;
679
- }
680
- /**
681
- * Generate Mocha tests for a function
682
- */
683
- generateMochaFunctionTests(fn) {
684
- const validParams = fn.parameters.map((p) => this.generateTestValue(p)).join(', ');
685
- const fnCall = fn.isAsync ? `await ${fn.name}(${validParams})` : `${fn.name}(${validParams})`;
686
- let code = ` describe('${fn.name}', function() {\n`;
687
- code += ` it('should handle valid input', ${fn.isAsync ? 'async ' : ''}function() {\n`;
688
- code += ` const result = ${fnCall};\n`;
689
- code += ` expect(result).to.not.be.undefined;\n`;
690
- code += ` });\n`;
691
- code += ` });\n\n`;
692
- return code;
693
- }
694
- /**
695
- * Generate Mocha tests for a class
696
- */
697
- generateMochaClassTests(cls) {
698
- const constructorArgs = cls.constructorParams?.map((p) => this.generateTestValue(p)).join(', ') || '';
699
- let code = ` describe('${cls.name}', function() {\n`;
700
- code += ` let instance;\n\n`;
701
- code += ` beforeEach(function() {\n`;
702
- code += ` instance = new ${cls.name}(${constructorArgs});\n`;
703
- code += ` });\n\n`;
704
- code += ` it('should instantiate correctly', function() {\n`;
705
- code += ` expect(instance).to.be.instanceOf(${cls.name});\n`;
706
- code += ` });\n`;
707
- for (const method of cls.methods) {
708
- if (!method.name.startsWith('_')) {
709
- const methodParams = method.parameters.map((p) => this.generateTestValue(p)).join(', ');
710
- code += `\n it('${method.name} should work', ${method.isAsync ? 'async ' : ''}function() {\n`;
711
- code += ` const result = ${method.isAsync ? 'await ' : ''}instance.${method.name}(${methodParams});\n`;
712
- code += ` expect(result).to.not.be.undefined;\n`;
713
- code += ` });\n`;
714
- }
715
- }
716
- code += ` });\n\n`;
717
- return code;
718
- }
719
- /**
720
- * Generate real Pytest test code
721
- */
722
- generateRealPytestTest(moduleName, importPath, testType, analysis, patterns) {
723
- const patternComment = patterns.length > 0
724
- ? `# Applied patterns: ${patterns.map((p) => p.name).join(', ')}\n`
725
- : '';
726
- const exports = [];
727
- for (const fn of analysis.functions) {
728
- if (fn.isExported)
729
- exports.push(fn.name);
730
- }
731
- for (const cls of analysis.classes) {
732
- if (cls.isExported)
733
- exports.push(cls.name);
734
- }
735
- const pythonImport = importPath.replace(/\//g, '.').replace(/\.(ts|js)$/, '');
736
- const importStatement = exports.length > 0
737
- ? `from ${pythonImport} import ${exports.join(', ')}`
738
- : `import ${pythonImport} as ${moduleName}`;
739
- let code = `${patternComment}import pytest
740
- ${importStatement}
741
-
742
-
743
- class Test${moduleName.charAt(0).toUpperCase() + moduleName.slice(1)}:
744
- """${testType} tests for ${moduleName}"""
745
-
746
- `;
747
- for (const fn of analysis.functions) {
748
- code += this.generatePytestFunctionTests(fn);
749
- }
750
- for (const cls of analysis.classes) {
751
- code += this.generatePytestClassTests(cls);
752
- }
753
- return code;
754
- }
755
- /**
756
- * Generate Pytest tests for a function
757
- */
758
- generatePytestFunctionTests(fn) {
759
- const validParams = fn.parameters.map((p) => this.generatePythonTestValue(p)).join(', ');
760
- let code = ` def test_${fn.name}_valid_input(self):\n`;
761
- code += ` """Test ${fn.name} with valid input"""\n`;
762
- code += ` result = ${fn.name}(${validParams})\n`;
763
- code += ` assert result is not None\n\n`;
764
- return code;
765
- }
766
- /**
767
- * Generate Pytest tests for a class
768
- */
769
- generatePytestClassTests(cls) {
770
- const constructorArgs = cls.constructorParams?.map((p) => this.generatePythonTestValue(p)).join(', ') || '';
771
- let code = `\nclass Test${cls.name}:\n`;
772
- code += ` """Tests for ${cls.name}"""\n\n`;
773
- code += ` @pytest.fixture\n`;
774
- code += ` def instance(self):\n`;
775
- code += ` return ${cls.name}(${constructorArgs})\n\n`;
776
- code += ` def test_instantiation(self, instance):\n`;
777
- code += ` assert isinstance(instance, ${cls.name})\n\n`;
778
- for (const method of cls.methods) {
779
- if (!method.name.startsWith('_')) {
780
- const methodParams = method.parameters.map((p) => this.generatePythonTestValue(p)).join(', ');
781
- code += ` def test_${method.name}(self, instance):\n`;
782
- code += ` result = instance.${method.name}(${methodParams})\n`;
783
- code += ` assert result is not None\n\n`;
784
- }
785
- }
786
- return code;
787
- }
788
- /**
789
- * Generate a Python test value for a parameter
790
- */
791
- generatePythonTestValue(param) {
792
- const type = param.type?.toLowerCase() || 'unknown';
793
- const name = param.name.toLowerCase();
794
- if (name.includes('id'))
795
- return `"${faker.string.uuid()}"`;
796
- if (name.includes('name'))
797
- return `"${faker.person.fullName()}"`;
798
- if (name.includes('email'))
799
- return `"${faker.internet.email()}"`;
800
- if (type.includes('str'))
801
- return `"${faker.lorem.word()}"`;
802
- if (type.includes('int') || type.includes('number')) {
803
- return String(faker.number.int({ min: 1, max: 100 }));
804
- }
805
- if (type.includes('bool'))
806
- return 'True';
807
- if (type.includes('list') || type.includes('[]'))
808
- return '[]';
809
- if (type.includes('dict') || type.includes('{}'))
810
- return '{}';
811
- return 'None';
812
- }
354
+ // ============================================================================
355
+ // Private Helper Methods - Utility Functions
356
+ // ============================================================================
813
357
  async findApplicablePatterns(sourceFile, requestedPatterns) {
814
358
  const patterns = [];
815
- // Check memory for stored patterns
816
359
  for (const patternName of requestedPatterns) {
817
360
  const stored = await this.memory.get(`pattern:${patternName}`);
818
361
  if (stored) {
819
362
  patterns.push(stored);
820
363
  }
821
364
  }
822
- // Also search for patterns by file type
823
365
  const extension = sourceFile.split('.').pop() || '';
824
366
  const searchResults = await this.memory.search(`pattern:*:${extension}`, 5);
825
367
  for (const key of searchResults) {
@@ -830,1313 +372,6 @@ class Test${moduleName.charAt(0).toUpperCase() + moduleName.slice(1)}:
830
372
  }
831
373
  return patterns;
832
374
  }
833
- generateStubTestCode(sourceFile, testType, framework, patterns) {
834
- const moduleName = this.extractModuleName(sourceFile);
835
- const importPath = this.getImportPath(sourceFile);
836
- // Generate framework-specific test template
837
- switch (framework) {
838
- case 'jest':
839
- case 'vitest':
840
- return this.generateJestVitestTest(moduleName, importPath, testType, patterns);
841
- case 'mocha':
842
- return this.generateMochaTest(moduleName, importPath, testType, patterns);
843
- case 'pytest':
844
- return this.generatePytestTest(moduleName, importPath, testType, patterns);
845
- default:
846
- return this.generateJestVitestTest(moduleName, importPath, testType, patterns);
847
- }
848
- }
849
- generateJestVitestTest(moduleName, importPath, testType, patterns) {
850
- const patternComment = patterns.length > 0
851
- ? `// Applied patterns: ${patterns.map((p) => p.name).join(', ')}\n`
852
- : '';
853
- // Generate pattern-aware test implementations
854
- const basicOpsTest = this.generateBasicOpsTest(moduleName, patterns);
855
- const edgeCaseTest = this.generateEdgeCaseTest(moduleName, patterns);
856
- const errorHandlingTest = this.generateErrorHandlingTest(moduleName, patterns);
857
- return `${patternComment}import { ${moduleName} } from '${importPath}';
858
-
859
- describe('${moduleName}', () => {
860
- describe('${testType} tests', () => {
861
- it('should be defined', () => {
862
- expect(${moduleName}).toBeDefined();
863
- });
864
-
865
- ${basicOpsTest}
866
- ${edgeCaseTest}
867
- ${errorHandlingTest}
868
- });
869
- });
870
- `;
871
- }
872
- /**
873
- * Generate basic operations test based on patterns
874
- */
875
- generateBasicOpsTest(moduleName, patterns) {
876
- // Check for service pattern
877
- const isService = patterns.some((p) => p.name.toLowerCase().includes('service') || p.name.toLowerCase().includes('repository'));
878
- // Check for factory pattern
879
- const isFactory = patterns.some((p) => p.name.toLowerCase().includes('factory'));
880
- // Check for async patterns
881
- const hasAsyncPattern = patterns.some((p) => p.name.toLowerCase().includes('async') || p.name.toLowerCase().includes('promise'));
882
- if (isService) {
883
- return ` it('should handle basic operations', async () => {
884
- // Service pattern: test core functionality
885
- const instance = new ${moduleName}();
886
- expect(instance).toBeInstanceOf(${moduleName});
887
-
888
- // Verify service is properly initialized
889
- const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance))
890
- .filter(m => m !== 'constructor');
891
- expect(methods.length).toBeGreaterThan(0);
892
- });`;
893
- }
894
- if (isFactory) {
895
- return ` it('should handle basic operations', () => {
896
- // Factory pattern: test object creation
897
- const result = ${moduleName}.create ? ${moduleName}.create() : new ${moduleName}();
898
- expect(result).toBeDefined();
899
- expect(typeof result).not.toBe('undefined');
900
- });`;
901
- }
902
- if (hasAsyncPattern) {
903
- return ` it('should handle basic operations', async () => {
904
- // Async pattern: test promise resolution
905
- const instance = typeof ${moduleName} === 'function'
906
- ? new ${moduleName}()
907
- : ${moduleName};
908
-
909
- // Verify async methods resolve properly
910
- if (typeof instance.execute === 'function') {
911
- await expect(instance.execute()).resolves.toBeDefined();
912
- }
913
- });`;
914
- }
915
- // Default implementation
916
- return ` it('should handle basic operations', () => {
917
- // Verify module exports expected interface
918
- const moduleType = typeof ${moduleName};
919
- expect(['function', 'object']).toContain(moduleType);
920
-
921
- if (moduleType === 'function') {
922
- // Class or function: verify instantiation
923
- const instance = new ${moduleName}();
924
- expect(instance).toBeDefined();
925
- } else {
926
- // Object module: verify properties exist
927
- expect(Object.keys(${moduleName}).length).toBeGreaterThan(0);
928
- }
929
- });`;
930
- }
931
- /**
932
- * Generate edge case test based on patterns
933
- */
934
- generateEdgeCaseTest(moduleName, patterns) {
935
- const hasValidation = patterns.some((p) => p.name.toLowerCase().includes('validation') || p.name.toLowerCase().includes('validator'));
936
- const hasCollection = patterns.some((p) => p.name.toLowerCase().includes('collection') || p.name.toLowerCase().includes('list'));
937
- if (hasValidation) {
938
- return ` it('should handle edge cases', () => {
939
- // Validation pattern: test boundary conditions
940
- const instance = new ${moduleName}();
941
-
942
- // Test with empty values
943
- if (typeof instance.validate === 'function') {
944
- expect(() => instance.validate('')).toBeDefined();
945
- expect(() => instance.validate(null)).toBeDefined();
946
- }
947
- });`;
948
- }
949
- if (hasCollection) {
950
- return ` it('should handle edge cases', () => {
951
- // Collection pattern: test empty and large datasets
952
- const instance = new ${moduleName}();
953
-
954
- // Empty collection should be handled gracefully
955
- if (typeof instance.add === 'function') {
956
- expect(() => instance.add(undefined)).toBeDefined();
957
- }
958
- if (typeof instance.get === 'function') {
959
- expect(instance.get('nonexistent')).toBeUndefined();
960
- }
961
- });`;
962
- }
963
- // Default edge case test
964
- return ` it('should handle edge cases', () => {
965
- // Test null/undefined handling
966
- const instance = typeof ${moduleName} === 'function'
967
- ? new ${moduleName}()
968
- : ${moduleName};
969
-
970
- // Module should handle edge case inputs gracefully
971
- expect(instance).toBeDefined();
972
- expect(() => JSON.stringify(instance)).not.toThrow();
973
- });`;
974
- }
975
- /**
976
- * Generate error handling test based on patterns
977
- */
978
- generateErrorHandlingTest(moduleName, patterns) {
979
- const hasErrorPattern = patterns.some((p) => p.name.toLowerCase().includes('error') || p.name.toLowerCase().includes('exception'));
980
- const hasAsyncPattern = patterns.some((p) => p.name.toLowerCase().includes('async') || p.name.toLowerCase().includes('promise'));
981
- if (hasAsyncPattern) {
982
- return ` it('should handle error conditions', async () => {
983
- // Async error handling: verify rejections are caught
984
- const instance = typeof ${moduleName} === 'function'
985
- ? new ${moduleName}()
986
- : ${moduleName};
987
-
988
- // Async operations should reject gracefully on invalid input
989
- const asyncMethods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance) || {})
990
- .filter(m => m !== 'constructor');
991
-
992
- // At minimum, module should be stable
993
- expect(instance).toBeDefined();
994
- });`;
995
- }
996
- if (hasErrorPattern) {
997
- return ` it('should handle error conditions', () => {
998
- // Error pattern: verify custom error types
999
- try {
1000
- const instance = new ${moduleName}();
1001
- // Trigger error condition if possible
1002
- if (typeof instance.throwError === 'function') {
1003
- expect(() => instance.throwError()).toThrow();
1004
- }
1005
- } catch (error) {
1006
- expect(error).toBeInstanceOf(Error);
1007
- }
1008
- });`;
1009
- }
1010
- // Default error handling test
1011
- return ` it('should handle error conditions', () => {
1012
- // Verify error resilience
1013
- expect(() => {
1014
- const instance = typeof ${moduleName} === 'function'
1015
- ? new ${moduleName}()
1016
- : ${moduleName};
1017
- return instance;
1018
- }).not.toThrow();
1019
-
1020
- // Module should not throw on inspection
1021
- expect(() => Object.keys(${moduleName})).not.toThrow();
1022
- });`;
1023
- }
1024
- generateMochaTest(moduleName, importPath, testType, patterns) {
1025
- const patternComment = patterns.length > 0
1026
- ? `// Applied patterns: ${patterns.map((p) => p.name).join(', ')}\n`
1027
- : '';
1028
- // Determine if async tests needed based on patterns
1029
- const isAsync = patterns.some((p) => p.name.toLowerCase().includes('async') || p.name.toLowerCase().includes('promise'));
1030
- const asyncSetup = isAsync ? 'async ' : '';
1031
- return `${patternComment}import { expect } from 'chai';
1032
- import { ${moduleName} } from '${importPath}';
1033
-
1034
- describe('${moduleName}', function() {
1035
- describe('${testType} tests', function() {
1036
- it('should be defined', function() {
1037
- expect(${moduleName}).to.not.be.undefined;
1038
- });
1039
-
1040
- it('should handle basic operations', ${asyncSetup}function() {
1041
- // Verify module exports expected interface
1042
- const moduleType = typeof ${moduleName};
1043
- expect(['function', 'object']).to.include(moduleType);
1044
-
1045
- if (moduleType === 'function') {
1046
- const instance = new ${moduleName}();
1047
- expect(instance).to.exist;
1048
- } else {
1049
- expect(Object.keys(${moduleName})).to.have.length.greaterThan(0);
1050
- }
1051
- });
1052
-
1053
- it('should handle edge cases', function() {
1054
- // Verify resilience to edge inputs
1055
- const instance = typeof ${moduleName} === 'function'
1056
- ? new ${moduleName}()
1057
- : ${moduleName};
1058
- expect(instance).to.exist;
1059
- expect(() => JSON.stringify(instance)).to.not.throw();
1060
- });
1061
-
1062
- it('should handle error conditions', function() {
1063
- // Verify error resilience
1064
- expect(() => {
1065
- const instance = typeof ${moduleName} === 'function'
1066
- ? new ${moduleName}()
1067
- : ${moduleName};
1068
- return instance;
1069
- }).to.not.throw();
1070
- });
1071
- });
1072
- });
1073
- `;
1074
- }
1075
- generatePytestTest(moduleName, importPath, testType, patterns) {
1076
- const patternComment = patterns.length > 0
1077
- ? `# Applied patterns: ${patterns.map((p) => p.name).join(', ')}\n`
1078
- : '';
1079
- // Determine if async tests needed based on patterns
1080
- const isAsync = patterns.some((p) => p.name.toLowerCase().includes('async') || p.name.toLowerCase().includes('promise'));
1081
- const asyncDecorator = isAsync ? '@pytest.mark.asyncio\n ' : '';
1082
- const asyncDef = isAsync ? 'async def' : 'def';
1083
- return `${patternComment}import pytest
1084
- from ${importPath} import ${moduleName}
1085
-
1086
-
1087
- class Test${moduleName}:
1088
- """${testType} tests for ${moduleName}"""
1089
-
1090
- def test_is_defined(self):
1091
- """Verify the module is properly exported and defined."""
1092
- assert ${moduleName} is not None
1093
-
1094
- ${asyncDecorator}${asyncDef} test_basic_operations(self):
1095
- """Test core functionality with valid inputs."""
1096
- # Verify module can be instantiated or accessed
1097
- if callable(${moduleName}):
1098
- instance = ${moduleName}()
1099
- assert instance is not None
1100
- else:
1101
- assert len(dir(${moduleName})) > 0
1102
-
1103
- def test_edge_cases(self):
1104
- """Test handling of edge case inputs."""
1105
- # Verify module handles edge cases gracefully
1106
- instance = ${moduleName}() if callable(${moduleName}) else ${moduleName}
1107
- assert instance is not None
1108
- # Module should be serializable
1109
- import json
1110
- try:
1111
- json.dumps(str(instance))
1112
- except (TypeError, ValueError):
1113
- pass # Complex objects may not serialize, but shouldn't crash
1114
-
1115
- def test_error_conditions(self):
1116
- """Test error handling and recovery."""
1117
- # Module instantiation should not raise unexpected errors
1118
- try:
1119
- instance = ${moduleName}() if callable(${moduleName}) else ${moduleName}
1120
- assert instance is not None
1121
- except TypeError:
1122
- # Expected if constructor requires arguments
1123
- pass
1124
- `;
1125
- }
1126
- async generateRedPhaseTest(feature, behavior, _framework) {
1127
- // Generate TDD RED phase: failing test that defines expected behavior
1128
- const funcName = this.camelCase(feature);
1129
- const assertions = this.generateAssertionsFromBehavior(behavior, funcName);
1130
- const testCode = `describe('${feature}', () => {
1131
- it('${behavior}', () => {
1132
- // Red phase: This test should fail initially
1133
- ${assertions}
1134
- });
1135
- });`;
1136
- return {
1137
- phase: 'red',
1138
- testCode,
1139
- nextStep: 'Write the minimal implementation to make this test pass',
1140
- };
1141
- }
1142
- /**
1143
- * Generate specific assertions from behavior description
1144
- * Uses NLP-style extraction to infer test values and assertions
1145
- */
1146
- generateAssertionsFromBehavior(behavior, funcName) {
1147
- const behaviorLower = behavior.toLowerCase();
1148
- const assertions = [];
1149
- // Extract context from behavior description
1150
- const context = this.extractBehaviorContext(behavior);
1151
- // Build function call with appropriate arguments
1152
- const funcCall = this.buildFunctionCall(funcName, context, behaviorLower);
1153
- // Add setup if needed
1154
- if (context.setupCode) {
1155
- assertions.push(context.setupCode);
1156
- }
1157
- // Generate assertions based on expected outcome
1158
- if (behaviorLower.includes('return') && behaviorLower.includes('true')) {
1159
- assertions.push(` const result = ${funcCall};`);
1160
- assertions.push(` expect(result).toBe(true);`);
1161
- }
1162
- else if (behaviorLower.includes('return') && behaviorLower.includes('false')) {
1163
- assertions.push(` const result = ${funcCall};`);
1164
- assertions.push(` expect(result).toBe(false);`);
1165
- }
1166
- else if (behaviorLower.includes('throw') || behaviorLower.includes('error')) {
1167
- const errorMsg = context.extractedString || 'Error';
1168
- assertions.push(` expect(() => ${funcCall}).toThrow(${context.extractedString ? `'${errorMsg}'` : ''});`);
1169
- }
1170
- else if (behaviorLower.includes('empty') || behaviorLower.includes('nothing')) {
1171
- assertions.push(` const result = ${funcCall};`);
1172
- if (behaviorLower.includes('string')) {
1173
- assertions.push(` expect(result).toBe('');`);
1174
- }
1175
- else if (behaviorLower.includes('object')) {
1176
- assertions.push(` expect(result).toEqual({});`);
1177
- }
1178
- else {
1179
- assertions.push(` expect(result).toEqual([]);`);
1180
- }
1181
- }
1182
- else if (behaviorLower.includes('null')) {
1183
- assertions.push(` const result = ${funcCall};`);
1184
- assertions.push(` expect(result).toBeNull();`);
1185
- }
1186
- else if (behaviorLower.includes('undefined')) {
1187
- assertions.push(` const result = ${funcCall};`);
1188
- assertions.push(` expect(result).toBeUndefined();`);
1189
- }
1190
- else if (behaviorLower.includes('contain') || behaviorLower.includes('include')) {
1191
- assertions.push(` const result = ${funcCall};`);
1192
- const expectedValue = context.extractedString || context.extractedNumber?.toString() || 'expectedItem';
1193
- if (context.extractedString) {
1194
- assertions.push(` expect(result).toContain('${expectedValue}');`);
1195
- }
1196
- else if (context.extractedNumber !== undefined) {
1197
- assertions.push(` expect(result).toContain(${expectedValue});`);
1198
- }
1199
- else {
1200
- assertions.push(` expect(result).toContain(testInput); // Contains the input`);
1201
- }
1202
- }
1203
- else if (behaviorLower.includes('length') || behaviorLower.includes('count')) {
1204
- assertions.push(` const result = ${funcCall};`);
1205
- const expectedLength = context.extractedNumber ?? 3;
1206
- assertions.push(` expect(result).toHaveLength(${expectedLength});`);
1207
- }
1208
- else if (behaviorLower.includes('equal') || behaviorLower.includes('match')) {
1209
- assertions.push(` const result = ${funcCall};`);
1210
- if (context.extractedString) {
1211
- assertions.push(` expect(result).toEqual('${context.extractedString}');`);
1212
- }
1213
- else if (context.extractedNumber !== undefined) {
1214
- assertions.push(` expect(result).toEqual(${context.extractedNumber});`);
1215
- }
1216
- else {
1217
- assertions.push(` expect(result).toEqual(expectedOutput);`);
1218
- }
1219
- }
1220
- else if (behaviorLower.includes('greater') || behaviorLower.includes('more than')) {
1221
- assertions.push(` const result = ${funcCall};`);
1222
- const threshold = context.extractedNumber ?? 0;
1223
- assertions.push(` expect(result).toBeGreaterThan(${threshold});`);
1224
- }
1225
- else if (behaviorLower.includes('less') || behaviorLower.includes('fewer')) {
1226
- assertions.push(` const result = ${funcCall};`);
1227
- const threshold = context.extractedNumber ?? 100;
1228
- assertions.push(` expect(result).toBeLessThan(${threshold});`);
1229
- }
1230
- else if (behaviorLower.includes('valid') || behaviorLower.includes('success')) {
1231
- assertions.push(` const result = ${funcCall};`);
1232
- assertions.push(` expect(result).toBeDefined();`);
1233
- if (behaviorLower.includes('object') || behaviorLower.includes('response')) {
1234
- assertions.push(` expect(result.success ?? result.valid ?? result.ok).toBeTruthy();`);
1235
- }
1236
- else {
1237
- assertions.push(` expect(result).toBeTruthy();`);
1238
- }
1239
- }
1240
- else if (behaviorLower.includes('array') || behaviorLower.includes('list')) {
1241
- assertions.push(` const result = ${funcCall};`);
1242
- assertions.push(` expect(Array.isArray(result)).toBe(true);`);
1243
- if (context.extractedNumber !== undefined) {
1244
- assertions.push(` expect(result.length).toBeGreaterThanOrEqual(${context.extractedNumber});`);
1245
- }
1246
- }
1247
- else if (behaviorLower.includes('object')) {
1248
- assertions.push(` const result = ${funcCall};`);
1249
- assertions.push(` expect(typeof result).toBe('object');`);
1250
- assertions.push(` expect(result).not.toBeNull();`);
1251
- }
1252
- else if (behaviorLower.includes('string')) {
1253
- assertions.push(` const result = ${funcCall};`);
1254
- assertions.push(` expect(typeof result).toBe('string');`);
1255
- if (context.extractedString) {
1256
- assertions.push(` expect(result).toContain('${context.extractedString}');`);
1257
- }
1258
- }
1259
- else if (behaviorLower.includes('number')) {
1260
- assertions.push(` const result = ${funcCall};`);
1261
- assertions.push(` expect(typeof result).toBe('number');`);
1262
- assertions.push(` expect(Number.isNaN(result)).toBe(false);`);
1263
- }
1264
- else {
1265
- // Default: check it's defined
1266
- assertions.push(` const result = ${funcCall};`);
1267
- assertions.push(` expect(result).toBeDefined();`);
1268
- }
1269
- return assertions.join('\n');
1270
- }
1271
- /**
1272
- * Extract contextual information from behavior description
1273
- */
1274
- extractBehaviorContext(behavior) {
1275
- const context = {};
1276
- // Extract quoted strings from behavior
1277
- const stringMatch = behavior.match(/["']([^"']+)["']/);
1278
- if (stringMatch) {
1279
- context.extractedString = stringMatch[1];
1280
- }
1281
- // Extract numbers from behavior
1282
- const numberMatch = behavior.match(/\b(\d+)\b/);
1283
- if (numberMatch) {
1284
- context.extractedNumber = parseInt(numberMatch[1], 10);
1285
- }
1286
- // Detect input type
1287
- if (/\b(email|e-mail)\b/i.test(behavior)) {
1288
- context.inputType = 'email';
1289
- context.setupCode = ` const testInput = 'test@example.com';`;
1290
- }
1291
- else if (/\b(url|link|href)\b/i.test(behavior)) {
1292
- context.inputType = 'url';
1293
- context.setupCode = ` const testInput = 'https://example.com';`;
1294
- }
1295
- else if (/\b(date|time|timestamp)\b/i.test(behavior)) {
1296
- context.inputType = 'date';
1297
- context.setupCode = ` const testInput = new Date('2024-01-15');`;
1298
- }
1299
- else if (/\b(id|uuid|identifier)\b/i.test(behavior)) {
1300
- context.inputType = 'id';
1301
- context.setupCode = ` const testInput = 'abc-123-def';`;
1302
- }
1303
- else if (/\b(user|person|customer)\b/i.test(behavior)) {
1304
- context.inputType = 'user';
1305
- context.setupCode = ` const testInput = { id: '1', name: 'Test User', email: 'test@example.com' };`;
1306
- }
1307
- else if (/\b(config|options|settings)\b/i.test(behavior)) {
1308
- context.inputType = 'config';
1309
- context.setupCode = ` const testInput = { enabled: true, timeout: 5000 };`;
1310
- }
1311
- return context;
1312
- }
1313
- /**
1314
- * Build function call with appropriate arguments based on context
1315
- */
1316
- buildFunctionCall(funcName, context, behaviorLower) {
1317
- // If context has setup code, use testInput variable
1318
- if (context.inputType) {
1319
- return `${funcName}(testInput)`;
1320
- }
1321
- // No input needed
1322
- if (!behaviorLower.includes('with') && !behaviorLower.includes('given') && !behaviorLower.includes('for')) {
1323
- return `${funcName}()`;
1324
- }
1325
- // Infer input type from behavior
1326
- if (behaviorLower.includes('string') || behaviorLower.includes('text') || behaviorLower.includes('name')) {
1327
- const value = context.extractedString || 'test input';
1328
- return `${funcName}('${value}')`;
1329
- }
1330
- if (behaviorLower.includes('number') || behaviorLower.includes('count') || behaviorLower.includes('amount')) {
1331
- const value = context.extractedNumber ?? 42;
1332
- return `${funcName}(${value})`;
1333
- }
1334
- if (behaviorLower.includes('array') || behaviorLower.includes('list') || behaviorLower.includes('items')) {
1335
- return `${funcName}([1, 2, 3])`;
1336
- }
1337
- if (behaviorLower.includes('object') || behaviorLower.includes('data') || behaviorLower.includes('payload')) {
1338
- return `${funcName}({ key: 'value' })`;
1339
- }
1340
- if (behaviorLower.includes('boolean') || behaviorLower.includes('flag')) {
1341
- return `${funcName}(true)`;
1342
- }
1343
- // Default: use extracted value or generic input
1344
- if (context.extractedString) {
1345
- return `${funcName}('${context.extractedString}')`;
1346
- }
1347
- if (context.extractedNumber !== undefined) {
1348
- return `${funcName}(${context.extractedNumber})`;
1349
- }
1350
- return `${funcName}(input)`;
1351
- }
1352
- async generateGreenPhaseCode(feature, behavior, _framework) {
1353
- // Generate TDD GREEN phase: minimal implementation to pass the test
1354
- // Analyze the behavior description to generate appropriate implementation
1355
- const behaviorLower = behavior.toLowerCase();
1356
- const funcName = this.camelCase(feature);
1357
- // Infer return type and implementation from behavior
1358
- const { returnType, implementation, params } = this.inferImplementationFromBehavior(behaviorLower);
1359
- const implementationCode = `/**
1360
- * ${feature}
1361
- * Behavior: ${behavior}
1362
- */
1363
- export function ${funcName}(${params}): ${returnType} {
1364
- ${implementation}
1365
- }`;
1366
- return {
1367
- phase: 'green',
1368
- implementationCode,
1369
- nextStep: 'Refactor the code while keeping tests green',
1370
- };
1371
- }
1372
- /**
1373
- * Infer implementation details from behavior description using heuristics
1374
- * Analyzes the behavior text to determine return type, parameters, and minimal implementation
1375
- */
1376
- inferImplementationFromBehavior(behavior) {
1377
- // Default values
1378
- let returnType = 'unknown';
1379
- let implementation = ' return undefined;';
1380
- let params = '';
1381
- // Detect return type from behavior description
1382
- if (behavior.includes('return') || behavior.includes('returns')) {
1383
- if (behavior.includes('boolean') || behavior.includes('true') || behavior.includes('false') ||
1384
- behavior.includes('valid') || behavior.includes('is ') || behavior.includes('has ') ||
1385
- behavior.includes('can ') || behavior.includes('should ')) {
1386
- returnType = 'boolean';
1387
- implementation = ' // Validate and return boolean result\n return true;';
1388
- }
1389
- else if (behavior.includes('number') || behavior.includes('count') || behavior.includes('sum') ||
1390
- behavior.includes('total') || behavior.includes('calculate') || behavior.includes('average')) {
1391
- returnType = 'number';
1392
- implementation = ' // Perform calculation and return result\n return 0;';
1393
- }
1394
- else if (behavior.includes('string') || behavior.includes('text') || behavior.includes('message') ||
1395
- behavior.includes('name') || behavior.includes('format')) {
1396
- returnType = 'string';
1397
- implementation = " // Process and return string result\n return '';";
1398
- }
1399
- else if (behavior.includes('array') || behavior.includes('list') || behavior.includes('items') ||
1400
- behavior.includes('collection') || behavior.includes('filter') || behavior.includes('map')) {
1401
- returnType = 'unknown[]';
1402
- implementation = ' // Process and return array\n return [];';
1403
- }
1404
- else if (behavior.includes('object') || behavior.includes('data') || behavior.includes('result') ||
1405
- behavior.includes('response')) {
1406
- returnType = 'Record<string, unknown>';
1407
- implementation = ' // Build and return object\n return {};';
1408
- }
1409
- }
1410
- // Detect if async is needed
1411
- if (behavior.includes('async') || behavior.includes('await') || behavior.includes('promise') ||
1412
- behavior.includes('fetch') || behavior.includes('load') || behavior.includes('save') ||
1413
- behavior.includes('api') || behavior.includes('request')) {
1414
- returnType = `Promise<${returnType}>`;
1415
- implementation = implementation.replace('return ', 'return await Promise.resolve(').replace(';', ');');
1416
- }
1417
- // Detect parameters from behavior
1418
- const paramPatterns = [
1419
- { pattern: /(?:with|given|for|using)\s+(?:a\s+)?(?:string|text|name)/i, param: 'input: string' },
1420
- { pattern: /(?:with|given|for|using)\s+(?:a\s+)?(?:number|count|amount)/i, param: 'value: number' },
1421
- { pattern: /(?:with|given|for|using)\s+(?:an?\s+)?(?:array|list|items)/i, param: 'items: unknown[]' },
1422
- { pattern: /(?:with|given|for|using)\s+(?:an?\s+)?(?:object|data)/i, param: 'data: Record<string, unknown>' },
1423
- { pattern: /(?:with|given|for|using)\s+(?:an?\s+)?id/i, param: 'id: string' },
1424
- { pattern: /(?:with|given|for|using)\s+(?:valid|invalid)\s+input/i, param: 'input: unknown' },
1425
- { pattern: /(?:when|if)\s+(?:called\s+)?(?:with|without)/i, param: 'input?: unknown' },
1426
- ];
1427
- const detectedParams = [];
1428
- for (const { pattern, param } of paramPatterns) {
1429
- if (pattern.test(behavior) && !detectedParams.includes(param)) {
1430
- detectedParams.push(param);
1431
- }
1432
- }
1433
- params = detectedParams.join(', ');
1434
- // Detect validation logic from behavior
1435
- if (behavior.includes('validate') || behavior.includes('check') || behavior.includes('verify')) {
1436
- if (params.includes('input')) {
1437
- implementation = ` // Validate the input
1438
- if (input === undefined || input === null) {
1439
- throw new Error('Invalid input');
1440
- }
1441
- ${implementation}`;
1442
- }
1443
- }
1444
- // Detect error throwing from behavior
1445
- if (behavior.includes('throw') || behavior.includes('error') || behavior.includes('exception') ||
1446
- behavior.includes('invalid') || behavior.includes('fail')) {
1447
- if (behavior.includes('when') || behavior.includes('if')) {
1448
- implementation = ` // Check for error conditions
1449
- if (!input) {
1450
- throw new Error('Validation failed');
1451
- }
1452
- ${implementation}`;
1453
- }
1454
- }
1455
- return { returnType, implementation, params };
1456
- }
1457
- async generateRefactoringSuggestions(_feature, _behavior) {
1458
- return {
1459
- phase: 'refactor',
1460
- refactoringChanges: [
1461
- 'Extract common logic into helper functions',
1462
- 'Apply single responsibility principle',
1463
- 'Consider adding type safety improvements',
1464
- 'Review naming conventions',
1465
- 'Optimize performance if needed',
1466
- ],
1467
- nextStep: 'Apply refactoring changes and ensure all tests still pass',
1468
- };
1469
- }
1470
- generatePropertyTestCode(funcName, property, constraints) {
1471
- // Analyze property description to generate appropriate generators and assertions
1472
- const propertyLower = property.toLowerCase();
1473
- const { generators, assertion, setupCode } = this.analyzePropertyForTestGeneration(propertyLower, funcName, constraints);
1474
- return `import * as fc from 'fast-check';
1475
-
1476
- describe('${funcName} property tests', () => {
1477
- it('${property}', () => {
1478
- ${setupCode}
1479
- fc.assert(
1480
- fc.property(${generators.join(', ')}, (${this.generatePropertyParams(generators)}) => {
1481
- const result = ${funcName}(${this.generatePropertyArgs(generators)});
1482
- ${assertion}
1483
- })
1484
- );
1485
- });
1486
- });`;
1487
- }
1488
- /**
1489
- * Analyze property description to determine generators and assertions
1490
- */
1491
- analyzePropertyForTestGeneration(propertyLower, funcName, constraints) {
1492
- const generators = [];
1493
- let assertion = 'return result !== undefined;';
1494
- let setupCode = '';
1495
- // Idempotent property: f(f(x)) === f(x)
1496
- if (propertyLower.includes('idempotent') || propertyLower.includes('same result')) {
1497
- generators.push(this.inferGeneratorFromConstraints(constraints, 'input'));
1498
- assertion = `// Idempotent: applying twice gives same result
1499
- const firstResult = ${funcName}(input);
1500
- const secondResult = ${funcName}(firstResult);
1501
- return JSON.stringify(firstResult) === JSON.stringify(secondResult);`;
1502
- }
1503
- // Commutative property: f(a, b) === f(b, a)
1504
- else if (propertyLower.includes('commutative') || propertyLower.includes('order independent')) {
1505
- const gen = this.inferGeneratorFromConstraints(constraints, 'value');
1506
- generators.push(gen, gen);
1507
- assertion = `// Commutative: order doesn't matter
1508
- const result1 = ${funcName}(a, b);
1509
- const result2 = ${funcName}(b, a);
1510
- return JSON.stringify(result1) === JSON.stringify(result2);`;
1511
- }
1512
- // Associative property: f(f(a, b), c) === f(a, f(b, c))
1513
- else if (propertyLower.includes('associative')) {
1514
- const gen = this.inferGeneratorFromConstraints(constraints, 'value');
1515
- generators.push(gen, gen, gen);
1516
- assertion = `// Associative: grouping doesn't matter
1517
- const left = ${funcName}(${funcName}(a, b), c);
1518
- const right = ${funcName}(a, ${funcName}(b, c));
1519
- return JSON.stringify(left) === JSON.stringify(right);`;
1520
- }
1521
- // Identity property: f(x, identity) === x
1522
- else if (propertyLower.includes('identity') || propertyLower.includes('neutral element')) {
1523
- generators.push(this.inferGeneratorFromConstraints(constraints, 'input'));
1524
- const identity = constraints.identity !== undefined ? String(constraints.identity) : '0';
1525
- setupCode = ` const identity = ${identity};`;
1526
- assertion = `// Identity: operation with identity returns original
1527
- const result = ${funcName}(input, identity);
1528
- return JSON.stringify(result) === JSON.stringify(input);`;
1529
- }
1530
- // Inverse property: f(f(x)) === x (e.g., encode/decode)
1531
- else if (propertyLower.includes('inverse') || propertyLower.includes('reversible') ||
1532
- propertyLower.includes('round-trip') || propertyLower.includes('encode') ||
1533
- propertyLower.includes('decode')) {
1534
- generators.push(this.inferGeneratorFromConstraints(constraints, 'input'));
1535
- const inverseFn = constraints.inverse || `${funcName}Inverse`;
1536
- assertion = `// Inverse: applying function and its inverse returns original
1537
- const encoded = ${funcName}(input);
1538
- const decoded = ${inverseFn}(encoded);
1539
- return JSON.stringify(decoded) === JSON.stringify(input);`;
1540
- }
1541
- // Distributive property: f(a, b + c) === f(a, b) + f(a, c)
1542
- else if (propertyLower.includes('distributive')) {
1543
- const gen = this.inferGeneratorFromConstraints(constraints, 'number');
1544
- generators.push(gen, gen, gen);
1545
- assertion = `// Distributive: f(a, b + c) === f(a, b) + f(a, c)
1546
- const left = ${funcName}(a, b + c);
1547
- const right = ${funcName}(a, b) + ${funcName}(a, c);
1548
- return Math.abs(left - right) < 0.0001;`;
1549
- }
1550
- // Monotonic property: a <= b implies f(a) <= f(b)
1551
- else if (propertyLower.includes('monotonic') || propertyLower.includes('preserves order') ||
1552
- propertyLower.includes('non-decreasing') || propertyLower.includes('sorted')) {
1553
- generators.push('fc.integer()', 'fc.integer()');
1554
- assertion = `// Monotonic: preserves order
1555
- const [small, large] = a <= b ? [a, b] : [b, a];
1556
- const resultSmall = ${funcName}(small);
1557
- const resultLarge = ${funcName}(large);
1558
- return resultSmall <= resultLarge;`;
1559
- }
1560
- // Bounds/range property: output is within expected bounds
1561
- else if (propertyLower.includes('bound') || propertyLower.includes('range') ||
1562
- propertyLower.includes('between') || propertyLower.includes('clamp')) {
1563
- generators.push(this.inferGeneratorFromConstraints(constraints, 'input'));
1564
- const min = constraints.min !== undefined ? constraints.min : 0;
1565
- const max = constraints.max !== undefined ? constraints.max : 100;
1566
- assertion = `// Bounded: result is within expected range
1567
- const result = ${funcName}(input);
1568
- return result >= ${min} && result <= ${max};`;
1569
- }
1570
- // Length preservation
1571
- else if (propertyLower.includes('length') || propertyLower.includes('size')) {
1572
- generators.push('fc.array(fc.anything())');
1573
- if (propertyLower.includes('preserve')) {
1574
- assertion = `// Length preserved: output has same length as input
1575
- const result = ${funcName}(input);
1576
- return Array.isArray(result) && result.length === input.length;`;
1577
- }
1578
- else {
1579
- assertion = `// Length invariant
1580
- const result = ${funcName}(input);
1581
- return typeof result.length === 'number' || typeof result.size === 'number';`;
1582
- }
1583
- }
1584
- // Type preservation
1585
- else if (propertyLower.includes('type') && propertyLower.includes('preserve')) {
1586
- generators.push('fc.anything()');
1587
- assertion = `// Type preserved: output has same type as input
1588
- const result = ${funcName}(input);
1589
- return typeof result === typeof input;`;
1590
- }
1591
- // Non-null/defined output
1592
- else if (propertyLower.includes('never null') || propertyLower.includes('always defined') ||
1593
- propertyLower.includes('non-null')) {
1594
- generators.push(this.inferGeneratorFromConstraints(constraints, 'input'));
1595
- assertion = `// Never null: always returns defined value
1596
- const result = ${funcName}(input);
1597
- return result !== null && result !== undefined;`;
1598
- }
1599
- // Deterministic property: same input always produces same output
1600
- else if (propertyLower.includes('deterministic') || propertyLower.includes('pure') ||
1601
- propertyLower.includes('consistent')) {
1602
- generators.push(this.inferGeneratorFromConstraints(constraints, 'input'));
1603
- assertion = `// Deterministic: same input always gives same output
1604
- const result1 = ${funcName}(input);
1605
- const result2 = ${funcName}(input);
1606
- return JSON.stringify(result1) === JSON.stringify(result2);`;
1607
- }
1608
- // Default case: basic existence check with type-appropriate generator
1609
- else {
1610
- generators.push(this.inferGeneratorFromConstraints(constraints, 'input'));
1611
- assertion = `// Basic property: function returns a value
1612
- return result !== undefined;`;
1613
- }
1614
- return { generators, assertion, setupCode };
1615
- }
1616
- /**
1617
- * Infer the appropriate fast-check generator from constraints
1618
- */
1619
- inferGeneratorFromConstraints(constraints, hint) {
1620
- // Check explicit type constraint
1621
- const type = constraints.type?.toLowerCase() || hint.toLowerCase();
1622
- if (type.includes('string') || type.includes('text')) {
1623
- const minLength = constraints.minLength;
1624
- const maxLength = constraints.maxLength;
1625
- if (minLength !== undefined || maxLength !== undefined) {
1626
- return `fc.string({ minLength: ${minLength ?? 0}, maxLength: ${maxLength ?? 100} })`;
1627
- }
1628
- return 'fc.string()';
1629
- }
1630
- if (type.includes('number') || type.includes('int') || type.includes('value')) {
1631
- const min = constraints.min;
1632
- const max = constraints.max;
1633
- if (min !== undefined || max !== undefined) {
1634
- return `fc.integer({ min: ${min ?? Number.MIN_SAFE_INTEGER}, max: ${max ?? Number.MAX_SAFE_INTEGER} })`;
1635
- }
1636
- return 'fc.integer()';
1637
- }
1638
- if (type.includes('float') || type.includes('decimal')) {
1639
- return 'fc.float()';
1640
- }
1641
- if (type.includes('boolean') || type.includes('bool')) {
1642
- return 'fc.boolean()';
1643
- }
1644
- if (type.includes('array') || type.includes('list')) {
1645
- const itemType = constraints.itemType || 'anything';
1646
- const itemGen = this.getSimpleGenerator(itemType);
1647
- return `fc.array(${itemGen})`;
1648
- }
1649
- if (type.includes('object') || type.includes('record')) {
1650
- return 'fc.object()';
1651
- }
1652
- if (type.includes('date')) {
1653
- return 'fc.date()';
1654
- }
1655
- if (type.includes('uuid') || type.includes('id')) {
1656
- return 'fc.uuid()';
1657
- }
1658
- if (type.includes('email')) {
1659
- return 'fc.emailAddress()';
1660
- }
1661
- // Default to anything
1662
- return 'fc.anything()';
1663
- }
1664
- /**
1665
- * Get a simple generator for a type name
1666
- */
1667
- getSimpleGenerator(typeName) {
1668
- const typeMap = {
1669
- string: 'fc.string()',
1670
- number: 'fc.integer()',
1671
- integer: 'fc.integer()',
1672
- float: 'fc.float()',
1673
- boolean: 'fc.boolean()',
1674
- date: 'fc.date()',
1675
- uuid: 'fc.uuid()',
1676
- anything: 'fc.anything()',
1677
- };
1678
- return typeMap[typeName.toLowerCase()] || 'fc.anything()';
1679
- }
1680
- /**
1681
- * Generate parameter names from generator list
1682
- */
1683
- generatePropertyParams(generators) {
1684
- if (generators.length === 1) {
1685
- return 'input';
1686
- }
1687
- return generators.map((_, i) => String.fromCharCode(97 + i)).join(', '); // a, b, c...
1688
- }
1689
- /**
1690
- * Generate argument list for function call
1691
- */
1692
- generatePropertyArgs(generators) {
1693
- if (generators.length === 1) {
1694
- return 'input';
1695
- }
1696
- return generators.map((_, i) => String.fromCharCode(97 + i)).join(', ');
1697
- }
1698
- inferGenerators(property, constraints) {
1699
- const generators = [];
1700
- const propertyLower = property.toLowerCase();
1701
- // Analyze property description to infer appropriate generators
1702
- // String-related properties
1703
- if (propertyLower.includes('string') ||
1704
- propertyLower.includes('text') ||
1705
- propertyLower.includes('name') ||
1706
- propertyLower.includes('email')) {
1707
- if (constraints.minLength || constraints.maxLength) {
1708
- const min = constraints.minLength ?? 0;
1709
- const max = constraints.maxLength ?? 100;
1710
- generators.push(`fc.string({ minLength: ${min}, maxLength: ${max} })`);
1711
- }
1712
- else {
1713
- generators.push('fc.string()');
1714
- }
1715
- if (propertyLower.includes('email')) {
1716
- generators.push('fc.emailAddress()');
1717
- }
1718
- }
1719
- // Number-related properties
1720
- if (propertyLower.includes('number') ||
1721
- propertyLower.includes('count') ||
1722
- propertyLower.includes('amount') ||
1723
- propertyLower.includes('integer') ||
1724
- propertyLower.includes('positive') ||
1725
- propertyLower.includes('negative')) {
1726
- if (propertyLower.includes('positive')) {
1727
- generators.push('fc.nat()');
1728
- }
1729
- else if (propertyLower.includes('negative')) {
1730
- generators.push('fc.integer({ max: -1 })');
1731
- }
1732
- else if (constraints.min !== undefined || constraints.max !== undefined) {
1733
- const min = constraints.min ?? Number.MIN_SAFE_INTEGER;
1734
- const max = constraints.max ?? Number.MAX_SAFE_INTEGER;
1735
- generators.push(`fc.integer({ min: ${min}, max: ${max} })`);
1736
- }
1737
- else {
1738
- generators.push('fc.integer()');
1739
- }
1740
- if (propertyLower.includes('float') || propertyLower.includes('decimal')) {
1741
- generators.push('fc.float()');
1742
- }
1743
- }
1744
- // Boolean properties
1745
- if (propertyLower.includes('boolean') || propertyLower.includes('flag')) {
1746
- generators.push('fc.boolean()');
1747
- }
1748
- // Array-related properties
1749
- if (propertyLower.includes('array') ||
1750
- propertyLower.includes('list') ||
1751
- propertyLower.includes('collection')) {
1752
- const itemType = constraints.itemType || 'anything';
1753
- const itemGen = this.getGeneratorForType(itemType);
1754
- if (constraints.minItems || constraints.maxItems) {
1755
- const min = constraints.minItems ?? 0;
1756
- const max = constraints.maxItems ?? 10;
1757
- generators.push(`fc.array(${itemGen}, { minLength: ${min}, maxLength: ${max} })`);
1758
- }
1759
- else {
1760
- generators.push(`fc.array(${itemGen})`);
1761
- }
1762
- }
1763
- // Object-related properties
1764
- if (propertyLower.includes('object') || propertyLower.includes('record')) {
1765
- generators.push('fc.object()');
1766
- generators.push('fc.dictionary(fc.string(), fc.anything())');
1767
- }
1768
- // Date-related properties
1769
- if (propertyLower.includes('date') || propertyLower.includes('time')) {
1770
- generators.push('fc.date()');
1771
- }
1772
- // UUID properties
1773
- if (propertyLower.includes('uuid') || propertyLower.includes('id')) {
1774
- generators.push('fc.uuid()');
1775
- }
1776
- // Default fallback if no specific type detected
1777
- if (generators.length === 0) {
1778
- generators.push('fc.anything()');
1779
- }
1780
- return generators;
1781
- }
1782
- getGeneratorForType(type) {
1783
- const typeGenerators = {
1784
- string: 'fc.string()',
1785
- number: 'fc.integer()',
1786
- integer: 'fc.integer()',
1787
- float: 'fc.float()',
1788
- boolean: 'fc.boolean()',
1789
- date: 'fc.date()',
1790
- uuid: 'fc.uuid()',
1791
- anything: 'fc.anything()',
1792
- };
1793
- return typeGenerators[type.toLowerCase()] || 'fc.anything()';
1794
- }
1795
- collectArbitraries(tests) {
1796
- const arbitraries = new Set();
1797
- for (const test of tests) {
1798
- test.generators.forEach((g) => arbitraries.add(g));
1799
- }
1800
- return Array.from(arbitraries);
1801
- }
1802
- generateRecordFromSchema(schema, seed, locale) {
1803
- // Set faker locale and seed for reproducibility
1804
- faker.seed(seed);
1805
- if (locale && locale !== 'en') {
1806
- // Note: faker v8+ uses different locale handling
1807
- // For now, we use the default locale
1808
- }
1809
- const record = {};
1810
- for (const [key, fieldDef] of Object.entries(schema)) {
1811
- record[key] = this.generateValueForField(key, fieldDef, seed);
1812
- }
1813
- return record;
1814
- }
1815
- generateValueForField(fieldName, fieldDef, _seed) {
1816
- // Handle simple type strings
1817
- if (typeof fieldDef === 'string') {
1818
- return this.generateValueForType(fieldDef, fieldName);
1819
- }
1820
- // Handle complex field definitions
1821
- if (typeof fieldDef === 'object' && fieldDef !== null) {
1822
- const field = fieldDef;
1823
- // Use explicit faker method if specified
1824
- if (field.faker) {
1825
- return this.callFakerMethod(field.faker);
1826
- }
1827
- return this.generateValueForType(field.type, fieldName, field);
1828
- }
1829
- return null;
1830
- }
1831
- generateValueForType(type, fieldName, options) {
1832
- const normalizedType = type.toLowerCase();
1833
- // Try to infer the best faker method based on field name and type
1834
- switch (normalizedType) {
1835
- case 'string':
1836
- return this.generateStringValue(fieldName, options);
1837
- case 'number':
1838
- case 'int':
1839
- case 'integer':
1840
- return this.generateNumberValue(options);
1841
- case 'float':
1842
- case 'decimal':
1843
- return faker.number.float({ min: options?.min ?? 0, max: options?.max ?? 1000, fractionDigits: 2 });
1844
- case 'boolean':
1845
- case 'bool':
1846
- return faker.datatype.boolean();
1847
- case 'date':
1848
- case 'datetime':
1849
- return faker.date.recent().toISOString();
1850
- case 'email':
1851
- return faker.internet.email();
1852
- case 'uuid':
1853
- case 'id':
1854
- return faker.string.uuid();
1855
- case 'url':
1856
- return faker.internet.url();
1857
- case 'phone':
1858
- return faker.phone.number();
1859
- case 'address':
1860
- return this.generateAddress();
1861
- case 'name':
1862
- case 'fullname':
1863
- return faker.person.fullName();
1864
- case 'firstname':
1865
- return faker.person.firstName();
1866
- case 'lastname':
1867
- return faker.person.lastName();
1868
- case 'username':
1869
- return faker.internet.username();
1870
- case 'password':
1871
- return faker.internet.password();
1872
- case 'company':
1873
- return faker.company.name();
1874
- case 'jobtitle':
1875
- return faker.person.jobTitle();
1876
- case 'text':
1877
- case 'paragraph':
1878
- return faker.lorem.paragraph();
1879
- case 'sentence':
1880
- return faker.lorem.sentence();
1881
- case 'word':
1882
- case 'words':
1883
- return faker.lorem.word();
1884
- case 'avatar':
1885
- case 'image':
1886
- return faker.image.avatar();
1887
- case 'color':
1888
- return faker.color.rgb();
1889
- case 'ipaddress':
1890
- case 'ip':
1891
- return faker.internet.ipv4();
1892
- case 'mac':
1893
- return faker.internet.mac();
1894
- case 'latitude':
1895
- return faker.location.latitude();
1896
- case 'longitude':
1897
- return faker.location.longitude();
1898
- case 'country':
1899
- return faker.location.country();
1900
- case 'city':
1901
- return faker.location.city();
1902
- case 'zipcode':
1903
- case 'postalcode':
1904
- return faker.location.zipCode();
1905
- case 'creditcard':
1906
- return faker.finance.creditCardNumber();
1907
- case 'currency':
1908
- return faker.finance.currencyCode();
1909
- case 'amount':
1910
- case 'price':
1911
- return faker.finance.amount();
1912
- case 'json':
1913
- case 'object':
1914
- return { key: faker.lorem.word(), value: faker.lorem.sentence() };
1915
- case 'array':
1916
- return [faker.lorem.word(), faker.lorem.word(), faker.lorem.word()];
1917
- case 'enum':
1918
- if (options?.enum && options.enum.length > 0) {
1919
- return faker.helpers.arrayElement(options.enum);
1920
- }
1921
- return faker.lorem.word();
1922
- default:
1923
- // Try to infer from field name
1924
- return this.inferValueFromFieldName(fieldName);
1925
- }
1926
- }
1927
- generateStringValue(fieldName, options) {
1928
- const lowerName = fieldName.toLowerCase();
1929
- // Infer type from field name
1930
- if (lowerName.includes('email'))
1931
- return faker.internet.email();
1932
- if (lowerName.includes('name') && lowerName.includes('first'))
1933
- return faker.person.firstName();
1934
- if (lowerName.includes('name') && lowerName.includes('last'))
1935
- return faker.person.lastName();
1936
- if (lowerName.includes('name'))
1937
- return faker.person.fullName();
1938
- if (lowerName.includes('phone'))
1939
- return faker.phone.number();
1940
- if (lowerName.includes('address'))
1941
- return faker.location.streetAddress();
1942
- if (lowerName.includes('city'))
1943
- return faker.location.city();
1944
- if (lowerName.includes('country'))
1945
- return faker.location.country();
1946
- if (lowerName.includes('zip') || lowerName.includes('postal'))
1947
- return faker.location.zipCode();
1948
- if (lowerName.includes('url') || lowerName.includes('website'))
1949
- return faker.internet.url();
1950
- if (lowerName.includes('username') || lowerName.includes('user'))
1951
- return faker.internet.username();
1952
- if (lowerName.includes('password'))
1953
- return faker.internet.password();
1954
- if (lowerName.includes('description') || lowerName.includes('bio'))
1955
- return faker.lorem.paragraph();
1956
- if (lowerName.includes('title'))
1957
- return faker.lorem.sentence();
1958
- if (lowerName.includes('company'))
1959
- return faker.company.name();
1960
- if (lowerName.includes('job'))
1961
- return faker.person.jobTitle();
1962
- if (lowerName.includes('avatar') || lowerName.includes('image'))
1963
- return faker.image.avatar();
1964
- // Apply pattern if provided
1965
- if (options?.pattern) {
1966
- return faker.helpers.fromRegExp(options.pattern);
1967
- }
1968
- // Default string generation
1969
- return faker.lorem.words(3);
1970
- }
1971
- generateNumberValue(options) {
1972
- const min = options?.min ?? 0;
1973
- const max = options?.max ?? 10000;
1974
- return faker.number.int({ min, max });
1975
- }
1976
- generateAddress() {
1977
- return {
1978
- street: faker.location.streetAddress(),
1979
- city: faker.location.city(),
1980
- state: faker.location.state(),
1981
- zipCode: faker.location.zipCode(),
1982
- country: faker.location.country(),
1983
- };
1984
- }
1985
- inferValueFromFieldName(fieldName) {
1986
- const lowerName = fieldName.toLowerCase();
1987
- if (lowerName.includes('id'))
1988
- return faker.string.uuid();
1989
- if (lowerName.includes('email'))
1990
- return faker.internet.email();
1991
- if (lowerName.includes('name'))
1992
- return faker.person.fullName();
1993
- if (lowerName.includes('phone'))
1994
- return faker.phone.number();
1995
- if (lowerName.includes('date') || lowerName.includes('time'))
1996
- return faker.date.recent().toISOString();
1997
- if (lowerName.includes('url'))
1998
- return faker.internet.url();
1999
- if (lowerName.includes('count') || lowerName.includes('amount'))
2000
- return faker.number.int({ min: 0, max: 100 });
2001
- if (lowerName.includes('price'))
2002
- return faker.finance.amount();
2003
- if (lowerName.includes('active') || lowerName.includes('enabled') || lowerName.includes('is')) {
2004
- return faker.datatype.boolean();
2005
- }
2006
- // Default to a random string
2007
- return faker.lorem.word();
2008
- }
2009
- callFakerMethod(methodPath) {
2010
- try {
2011
- const parts = methodPath.split('.');
2012
- let result = faker;
2013
- for (const part of parts) {
2014
- if (result && typeof result === 'object' && part in result) {
2015
- const next = result[part];
2016
- if (typeof next === 'function') {
2017
- result = next();
2018
- }
2019
- else {
2020
- result = next;
2021
- }
2022
- }
2023
- else {
2024
- return faker.lorem.word();
2025
- }
2026
- }
2027
- return result;
2028
- }
2029
- catch {
2030
- return faker.lorem.word();
2031
- }
2032
- }
2033
- linkRelatedRecords(records, schema) {
2034
- // Find fields with references and link them
2035
- const referenceFields = [];
2036
- for (const [key, fieldDef] of Object.entries(schema)) {
2037
- if (typeof fieldDef === 'object' && fieldDef !== null) {
2038
- const field = fieldDef;
2039
- if (field.reference) {
2040
- referenceFields.push({ field: key, reference: field.reference });
2041
- }
2042
- }
2043
- }
2044
- // If we have reference fields, link records
2045
- if (referenceFields.length > 0) {
2046
- for (let i = 0; i < records.length; i++) {
2047
- const record = records[i];
2048
- for (const { field, reference } of referenceFields) {
2049
- // Link to a random previous record's ID or create a new one
2050
- if (i > 0 && reference === 'id') {
2051
- const prevRecord = records[Math.floor(Math.random() * i)];
2052
- record[field] = prevRecord['id'] ?? faker.string.uuid();
2053
- }
2054
- else {
2055
- record[field] = faker.string.uuid();
2056
- }
2057
- }
2058
- }
2059
- }
2060
- }
2061
- async generateTestForLines(file, lines, framework) {
2062
- if (lines.length === 0)
2063
- return null;
2064
- const testId = uuidv4();
2065
- const testFile = this.getTestFilePath(file, framework);
2066
- const moduleName = this.extractModuleName(file);
2067
- const importPath = this.getImportPath(file);
2068
- // Generate meaningful coverage test code
2069
- const testCode = this.generateCoverageTestCode(moduleName, importPath, lines, framework);
2070
- return {
2071
- id: testId,
2072
- name: `Coverage test for lines ${lines[0]}-${lines[lines.length - 1]}`,
2073
- sourceFile: file,
2074
- testFile,
2075
- testCode,
2076
- type: 'unit',
2077
- assertions: this.countAssertions(testCode),
2078
- };
2079
- }
2080
- /**
2081
- * Generate actual coverage test code for specific lines
2082
- */
2083
- generateCoverageTestCode(moduleName, importPath, lines, framework) {
2084
- const funcName = this.camelCase(moduleName);
2085
- const lineRange = lines.length === 1
2086
- ? `line ${lines[0]}`
2087
- : `lines ${lines[0]}-${lines[lines.length - 1]}`;
2088
- if (framework === 'pytest') {
2089
- return `# Coverage test for ${lineRange} in ${moduleName}
2090
- import pytest
2091
- from ${importPath.replace(/\//g, '.')} import ${funcName}
2092
-
2093
- class Test${this.pascalCase(moduleName)}Coverage:
2094
- """Tests to cover ${lineRange}"""
2095
-
2096
- def test_cover_${lines[0]}_${lines[lines.length - 1]}(self):
2097
- """Exercise code path covering ${lineRange}"""
2098
- # Arrange: Set up test inputs to reach uncovered lines
2099
- test_input = None # Replace with appropriate input
2100
-
2101
- # Act: Execute the code path
2102
- try:
2103
- result = ${funcName}(test_input)
2104
-
2105
- # Assert: Verify expected behavior
2106
- assert result is not None
2107
- except Exception as e:
2108
- # If exception is expected for this path, verify it
2109
- pytest.fail(f"Unexpected exception: {e}")
2110
- `;
2111
- }
2112
- // Default: Jest/Vitest format
2113
- return `// Coverage test for ${lineRange} in ${moduleName}
2114
- import { ${funcName} } from '${importPath}';
2115
-
2116
- describe('${moduleName} coverage', () => {
2117
- describe('${lineRange}', () => {
2118
- it('should execute code path covering ${lineRange}', () => {
2119
- // Arrange: Set up test inputs to reach uncovered lines
2120
- const testInput = undefined; // Replace with appropriate input
2121
-
2122
- // Act: Execute the code path
2123
- const result = ${funcName}(testInput);
2124
-
2125
- // Assert: Verify the code was reached and behaves correctly
2126
- expect(result).toBeDefined();
2127
- });
2128
-
2129
- it('should handle edge case for ${lineRange}', () => {
2130
- // Arrange: Set up edge case input
2131
- const edgeCaseInput = null;
2132
-
2133
- // Act & Assert: Verify edge case handling
2134
- expect(() => ${funcName}(edgeCaseInput)).not.toThrow();
2135
- });
2136
- });
2137
- });
2138
- `;
2139
- }
2140
375
  groupConsecutiveLines(lines) {
2141
376
  if (lines.length === 0)
2142
377
  return [];
@@ -2184,14 +419,10 @@ describe('${moduleName} coverage', () => {
2184
419
  return Math.max(1, count);
2185
420
  }
2186
421
  estimateCoverage(tests, target) {
2187
- // Estimate coverage based on test characteristics
2188
422
  const totalAssertions = tests.reduce((sum, t) => sum + t.assertions, 0);
2189
423
  const totalTests = tests.length;
2190
- // Base coverage from test count (each test covers ~3-5% typically)
2191
424
  const testBasedCoverage = totalTests * 4;
2192
- // Additional coverage from assertions (each assertion ~1-2%)
2193
425
  const assertionCoverage = totalAssertions * 1.5;
2194
- // Test type multipliers (integration tests cover more)
2195
426
  const typeMultiplier = tests.reduce((mult, t) => {
2196
427
  if (t.type === 'integration')
2197
428
  return mult + 0.1;
@@ -2199,23 +430,11 @@ describe('${moduleName} coverage', () => {
2199
430
  return mult + 0.15;
2200
431
  return mult;
2201
432
  }, 1);
2202
- // Calculate estimated coverage with diminishing returns
2203
433
  const rawEstimate = (testBasedCoverage + assertionCoverage) * typeMultiplier;
2204
- const diminishedEstimate = rawEstimate * (1 - rawEstimate / 200); // Diminishing returns above 100%
2205
- // Cap at target and round
434
+ const diminishedEstimate = rawEstimate * (1 - rawEstimate / 200);
2206
435
  const estimatedCoverage = Math.min(target, Math.max(0, diminishedEstimate));
2207
436
  return Math.round(estimatedCoverage * 10) / 10;
2208
437
  }
2209
- camelCase(str) {
2210
- return str
2211
- .replace(/[^a-zA-Z0-9]+(.)/g, (_, chr) => chr.toUpperCase())
2212
- .replace(/^./, (chr) => chr.toLowerCase());
2213
- }
2214
- pascalCase(str) {
2215
- return str
2216
- .replace(/[^a-zA-Z0-9]+(.)/g, (_, chr) => chr.toUpperCase())
2217
- .replace(/^./, (chr) => chr.toUpperCase());
2218
- }
2219
438
  async storeGenerationMetadata(tests, patterns) {
2220
439
  const metadata = {
2221
440
  generatedAt: new Date().toISOString(),
@@ -2223,8 +442,32 @@ describe('${moduleName} coverage', () => {
2223
442
  patterns,
2224
443
  testIds: tests.map((t) => t.id),
2225
444
  };
2226
- await this.memory.set(`test-generation:metadata:${Date.now()}`, metadata, { namespace: 'test-generation', ttl: 86400 * 7 } // 7 days
2227
- );
445
+ await this.memory.set(`test-generation:metadata:${Date.now()}`, metadata, { namespace: 'test-generation', ttl: 86400 * 7 });
2228
446
  }
2229
447
  }
448
+ // ============================================================================
449
+ // Factory Functions
450
+ // ============================================================================
451
+ /**
452
+ * Create a TestGeneratorService instance with default dependencies
453
+ * Maintains backward compatibility with existing code
454
+ *
455
+ * @param memory - Memory backend for pattern storage
456
+ * @param config - Optional configuration overrides
457
+ * @returns Configured TestGeneratorService instance
458
+ */
459
+ export function createTestGeneratorService(memory, config = {}) {
460
+ return new TestGeneratorService({ memory }, config);
461
+ }
462
+ /**
463
+ * Create a TestGeneratorService instance with custom dependencies
464
+ * Used for testing or when custom implementations are needed
465
+ *
466
+ * @param dependencies - All service dependencies
467
+ * @param config - Optional configuration overrides
468
+ * @returns Configured TestGeneratorService instance
469
+ */
470
+ export function createTestGeneratorServiceWithDependencies(dependencies, config = {}) {
471
+ return new TestGeneratorService(dependencies, config);
472
+ }
2230
473
  //# sourceMappingURL=test-generator.js.map