@avi770/testteam 1.2.0 → 3.0.0

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 (324) hide show
  1. package/CHANGELOG.md +53 -1
  2. package/README.md +72 -7
  3. package/agents/15-regression-sentinel.ts +3 -2
  4. package/agents/24-signup-onboarding-tester.ts +429 -0
  5. package/agents/25-crud-flow-tester.ts +302 -0
  6. package/agents/26-form-validator.ts +297 -0
  7. package/agents/27-search-filter-tester.ts +326 -0
  8. package/agents/28-navigation-routing-tester.ts +425 -0
  9. package/agents/29-responsive-interaction-tester.ts +350 -0
  10. package/agents/30-multi-user-scenario-tester.ts +319 -0
  11. package/agents/31-load-tester.ts +134 -0
  12. package/agents/32-memory-leak-detector.ts +194 -0
  13. package/agents/33-bundle-analyzer.ts +132 -0
  14. package/agents/34-xss-scanner.ts +191 -0
  15. package/agents/35-csrf-tester.ts +82 -0
  16. package/agents/36-auth-fuzzer.ts +194 -0
  17. package/agents/37-dependency-scanner.ts +176 -0
  18. package/agents/38-secrets-scanner.ts +137 -0
  19. package/agents/39-api-contract-tester.ts +199 -0
  20. package/agents/40-rate-limit-tester.ts +94 -0
  21. package/agents/41-api-pagination-tester.ts +97 -0
  22. package/agents/42-graphql-tester.ts +222 -0
  23. package/agents/43-data-consistency-checker.ts +205 -0
  24. package/agents/44-backup-recovery-tester.ts +152 -0
  25. package/agents/45-data-privacy-scanner.ts +125 -0
  26. package/agents/46-seo-auditor.ts +294 -0
  27. package/agents/47-social-preview-tester.ts +232 -0
  28. package/agents/48-lighthouse-auditor.ts +213 -0
  29. package/agents/49-i18n-tester.ts +198 -0
  30. package/agents/50-timezone-tester.ts +173 -0
  31. package/agents/51-error-recovery-tester.ts +155 -0
  32. package/agents/52-offline-mode-tester.ts +180 -0
  33. package/agents/53-graceful-degradation-tester.ts +156 -0
  34. package/agents/54-websocket-tester.ts +151 -0
  35. package/agents/55-realtime-sync-tester.ts +194 -0
  36. package/agents/56-file-upload-tester.ts +194 -0
  37. package/agents/57-export-tester.ts +174 -0
  38. package/agents/58-payment-flow-tester.ts +183 -0
  39. package/agents/59-ssl-tls-auditor.ts +141 -0
  40. package/agents/60-dns-cdn-tester.ts +117 -0
  41. package/agents/61-docker-health-checker.ts +111 -0
  42. package/agents/62-env-config-validator.ts +152 -0
  43. package/agents/63-log-quality-auditor.ts +136 -0
  44. package/agents/64-analytics-tracker-tester.ts +165 -0
  45. package/agents/65-gdpr-compliance-tester.ts +215 -0
  46. package/agents/66-soc2-control-validator.ts +210 -0
  47. package/agents/67-wcag-aaa-tester.ts +241 -0
  48. package/agents/68-dead-code-detector.ts +135 -0
  49. package/agents/69-type-safety-auditor.ts +164 -0
  50. package/agents/70-complexity-analyzer.ts +179 -0
  51. package/agents/__tests__/24-signup-onboarding-tester.test.ts +274 -0
  52. package/agents/__tests__/25-crud-flow-tester.test.ts +322 -0
  53. package/agents/__tests__/26-form-validator.test.ts +345 -0
  54. package/agents/__tests__/27-search-filter-tester.test.ts +311 -0
  55. package/agents/__tests__/28-navigation-routing-tester.test.ts +328 -0
  56. package/agents/__tests__/29-responsive-interaction-tester.test.ts +297 -0
  57. package/agents/__tests__/30-multi-user-scenario-tester.test.ts +328 -0
  58. package/agents/__tests__/31-load-tester.test.ts +189 -0
  59. package/agents/__tests__/32-memory-leak-detector.test.ts +251 -0
  60. package/agents/__tests__/33-bundle-analyzer.test.ts +237 -0
  61. package/agents/__tests__/34-xss-scanner.test.ts +258 -0
  62. package/agents/__tests__/35-csrf-tester.test.ts +200 -0
  63. package/agents/__tests__/36-auth-fuzzer.test.ts +214 -0
  64. package/agents/__tests__/37-dependency-scanner.test.ts +266 -0
  65. package/agents/__tests__/38-secrets-scanner.test.ts +224 -0
  66. package/agents/__tests__/39-api-contract-tester.test.ts +312 -0
  67. package/agents/__tests__/40-rate-limit-tester.test.ts +192 -0
  68. package/agents/__tests__/41-api-pagination-tester.test.ts +198 -0
  69. package/agents/__tests__/42-graphql-tester.test.ts +252 -0
  70. package/agents/__tests__/43-data-consistency-checker.test.ts +232 -0
  71. package/agents/__tests__/44-backup-recovery-tester.test.ts +222 -0
  72. package/agents/__tests__/45-data-privacy-scanner.test.ts +223 -0
  73. package/agents/__tests__/46-seo-auditor.test.ts +261 -0
  74. package/agents/__tests__/47-social-preview-tester.test.ts +245 -0
  75. package/agents/__tests__/48-lighthouse-auditor.test.ts +276 -0
  76. package/agents/__tests__/49-i18n-tester.test.ts +201 -0
  77. package/agents/__tests__/50-timezone-tester.test.ts +172 -0
  78. package/agents/__tests__/51-error-recovery-tester.test.ts +162 -0
  79. package/agents/__tests__/52-offline-mode-tester.test.ts +164 -0
  80. package/agents/__tests__/53-graceful-degradation-tester.test.ts +168 -0
  81. package/agents/__tests__/54-websocket-tester.test.ts +157 -0
  82. package/agents/__tests__/55-realtime-sync-tester.test.ts +181 -0
  83. package/agents/__tests__/56-file-upload-tester.test.ts +172 -0
  84. package/agents/__tests__/57-export-tester.test.ts +169 -0
  85. package/agents/__tests__/58-payment-flow-tester.test.ts +182 -0
  86. package/agents/__tests__/59-ssl-tls-auditor.test.ts +179 -0
  87. package/agents/__tests__/60-dns-cdn-tester.test.ts +176 -0
  88. package/agents/__tests__/61-docker-health-checker.test.ts +150 -0
  89. package/agents/__tests__/62-env-config-validator.test.ts +166 -0
  90. package/agents/__tests__/63-log-quality-auditor.test.ts +175 -0
  91. package/agents/__tests__/64-analytics-tracker-tester.test.ts +158 -0
  92. package/agents/__tests__/65-gdpr-compliance-tester.test.ts +174 -0
  93. package/agents/__tests__/66-soc2-control-validator.test.ts +183 -0
  94. package/agents/__tests__/67-wcag-aaa-tester.test.ts +190 -0
  95. package/agents/__tests__/68-dead-code-detector.test.ts +174 -0
  96. package/agents/__tests__/69-type-safety-auditor.test.ts +173 -0
  97. package/agents/__tests__/70-complexity-analyzer.test.ts +177 -0
  98. package/agents/__tests__/registry.test.ts +13 -13
  99. package/agents/base-agent.ts +8 -0
  100. package/agents/registry.ts +171 -28
  101. package/core/__tests__/integration.test.ts +4 -4
  102. package/core/__tests__/orchestrator.test.ts +17 -16
  103. package/core/cli.ts +128 -6
  104. package/core/license.ts +208 -211
  105. package/core/orchestrator.ts +78 -5
  106. package/dist/agents/15-regression-sentinel.d.ts +2 -1
  107. package/dist/agents/15-regression-sentinel.d.ts.map +1 -1
  108. package/dist/agents/15-regression-sentinel.js +2 -2
  109. package/dist/agents/15-regression-sentinel.js.map +1 -1
  110. package/dist/agents/24-signup-onboarding-tester.d.ts +35 -0
  111. package/dist/agents/24-signup-onboarding-tester.d.ts.map +1 -0
  112. package/dist/agents/24-signup-onboarding-tester.js +357 -0
  113. package/dist/agents/24-signup-onboarding-tester.js.map +1 -0
  114. package/dist/agents/25-crud-flow-tester.d.ts +11 -0
  115. package/dist/agents/25-crud-flow-tester.d.ts.map +1 -0
  116. package/dist/agents/25-crud-flow-tester.js +253 -0
  117. package/dist/agents/25-crud-flow-tester.js.map +1 -0
  118. package/dist/agents/26-form-validator.d.ts +12 -0
  119. package/dist/agents/26-form-validator.d.ts.map +1 -0
  120. package/dist/agents/26-form-validator.js +257 -0
  121. package/dist/agents/26-form-validator.js.map +1 -0
  122. package/dist/agents/27-search-filter-tester.d.ts +20 -0
  123. package/dist/agents/27-search-filter-tester.d.ts.map +1 -0
  124. package/dist/agents/27-search-filter-tester.js +267 -0
  125. package/dist/agents/27-search-filter-tester.js.map +1 -0
  126. package/dist/agents/28-navigation-routing-tester.d.ts +32 -0
  127. package/dist/agents/28-navigation-routing-tester.d.ts.map +1 -0
  128. package/dist/agents/28-navigation-routing-tester.js +363 -0
  129. package/dist/agents/28-navigation-routing-tester.js.map +1 -0
  130. package/dist/agents/29-responsive-interaction-tester.d.ts +26 -0
  131. package/dist/agents/29-responsive-interaction-tester.d.ts.map +1 -0
  132. package/dist/agents/29-responsive-interaction-tester.js +272 -0
  133. package/dist/agents/29-responsive-interaction-tester.js.map +1 -0
  134. package/dist/agents/30-multi-user-scenario-tester.d.ts +24 -0
  135. package/dist/agents/30-multi-user-scenario-tester.d.ts.map +1 -0
  136. package/dist/agents/30-multi-user-scenario-tester.js +254 -0
  137. package/dist/agents/30-multi-user-scenario-tester.js.map +1 -0
  138. package/dist/agents/31-load-tester.d.ts +12 -0
  139. package/dist/agents/31-load-tester.d.ts.map +1 -0
  140. package/dist/agents/31-load-tester.js +110 -0
  141. package/dist/agents/31-load-tester.js.map +1 -0
  142. package/dist/agents/32-memory-leak-detector.d.ts +12 -0
  143. package/dist/agents/32-memory-leak-detector.d.ts.map +1 -0
  144. package/dist/agents/32-memory-leak-detector.js +167 -0
  145. package/dist/agents/32-memory-leak-detector.js.map +1 -0
  146. package/dist/agents/33-bundle-analyzer.d.ts +10 -0
  147. package/dist/agents/33-bundle-analyzer.d.ts.map +1 -0
  148. package/dist/agents/33-bundle-analyzer.js +111 -0
  149. package/dist/agents/33-bundle-analyzer.js.map +1 -0
  150. package/dist/agents/34-xss-scanner.d.ts +11 -0
  151. package/dist/agents/34-xss-scanner.d.ts.map +1 -0
  152. package/dist/agents/34-xss-scanner.js +164 -0
  153. package/dist/agents/34-xss-scanner.js.map +1 -0
  154. package/dist/agents/35-csrf-tester.d.ts +11 -0
  155. package/dist/agents/35-csrf-tester.d.ts.map +1 -0
  156. package/dist/agents/35-csrf-tester.js +70 -0
  157. package/dist/agents/35-csrf-tester.js.map +1 -0
  158. package/dist/agents/36-auth-fuzzer.d.ts +13 -0
  159. package/dist/agents/36-auth-fuzzer.d.ts.map +1 -0
  160. package/dist/agents/36-auth-fuzzer.js +163 -0
  161. package/dist/agents/36-auth-fuzzer.js.map +1 -0
  162. package/dist/agents/37-dependency-scanner.d.ts +11 -0
  163. package/dist/agents/37-dependency-scanner.d.ts.map +1 -0
  164. package/dist/agents/37-dependency-scanner.js +139 -0
  165. package/dist/agents/37-dependency-scanner.js.map +1 -0
  166. package/dist/agents/38-secrets-scanner.d.ts +11 -0
  167. package/dist/agents/38-secrets-scanner.d.ts.map +1 -0
  168. package/dist/agents/38-secrets-scanner.js +116 -0
  169. package/dist/agents/38-secrets-scanner.js.map +1 -0
  170. package/dist/agents/39-api-contract-tester.d.ts +12 -0
  171. package/dist/agents/39-api-contract-tester.d.ts.map +1 -0
  172. package/dist/agents/39-api-contract-tester.js +142 -0
  173. package/dist/agents/39-api-contract-tester.js.map +1 -0
  174. package/dist/agents/40-rate-limit-tester.d.ts +12 -0
  175. package/dist/agents/40-rate-limit-tester.d.ts.map +1 -0
  176. package/dist/agents/40-rate-limit-tester.js +79 -0
  177. package/dist/agents/40-rate-limit-tester.js.map +1 -0
  178. package/dist/agents/41-api-pagination-tester.d.ts +12 -0
  179. package/dist/agents/41-api-pagination-tester.d.ts.map +1 -0
  180. package/dist/agents/41-api-pagination-tester.js +79 -0
  181. package/dist/agents/41-api-pagination-tester.js.map +1 -0
  182. package/dist/agents/42-graphql-tester.d.ts +13 -0
  183. package/dist/agents/42-graphql-tester.d.ts.map +1 -0
  184. package/dist/agents/42-graphql-tester.js +187 -0
  185. package/dist/agents/42-graphql-tester.js.map +1 -0
  186. package/dist/agents/43-data-consistency-checker.d.ts +11 -0
  187. package/dist/agents/43-data-consistency-checker.d.ts.map +1 -0
  188. package/dist/agents/43-data-consistency-checker.js +176 -0
  189. package/dist/agents/43-data-consistency-checker.js.map +1 -0
  190. package/dist/agents/44-backup-recovery-tester.d.ts +11 -0
  191. package/dist/agents/44-backup-recovery-tester.d.ts.map +1 -0
  192. package/dist/agents/44-backup-recovery-tester.js +128 -0
  193. package/dist/agents/44-backup-recovery-tester.js.map +1 -0
  194. package/dist/agents/45-data-privacy-scanner.d.ts +11 -0
  195. package/dist/agents/45-data-privacy-scanner.d.ts.map +1 -0
  196. package/dist/agents/45-data-privacy-scanner.js +100 -0
  197. package/dist/agents/45-data-privacy-scanner.js.map +1 -0
  198. package/dist/agents/46-seo-auditor.d.ts +12 -0
  199. package/dist/agents/46-seo-auditor.d.ts.map +1 -0
  200. package/dist/agents/46-seo-auditor.js +275 -0
  201. package/dist/agents/46-seo-auditor.js.map +1 -0
  202. package/dist/agents/47-social-preview-tester.d.ts +11 -0
  203. package/dist/agents/47-social-preview-tester.d.ts.map +1 -0
  204. package/dist/agents/47-social-preview-tester.js +219 -0
  205. package/dist/agents/47-social-preview-tester.js.map +1 -0
  206. package/dist/agents/48-lighthouse-auditor.d.ts +11 -0
  207. package/dist/agents/48-lighthouse-auditor.d.ts.map +1 -0
  208. package/dist/agents/48-lighthouse-auditor.js +192 -0
  209. package/dist/agents/48-lighthouse-auditor.js.map +1 -0
  210. package/dist/agents/49-i18n-tester.d.ts +13 -0
  211. package/dist/agents/49-i18n-tester.d.ts.map +1 -0
  212. package/dist/agents/49-i18n-tester.js +172 -0
  213. package/dist/agents/49-i18n-tester.js.map +1 -0
  214. package/dist/agents/50-timezone-tester.d.ts +11 -0
  215. package/dist/agents/50-timezone-tester.d.ts.map +1 -0
  216. package/dist/agents/50-timezone-tester.js +152 -0
  217. package/dist/agents/50-timezone-tester.js.map +1 -0
  218. package/dist/agents/51-error-recovery-tester.d.ts +11 -0
  219. package/dist/agents/51-error-recovery-tester.d.ts.map +1 -0
  220. package/dist/agents/51-error-recovery-tester.js +134 -0
  221. package/dist/agents/51-error-recovery-tester.js.map +1 -0
  222. package/dist/agents/52-offline-mode-tester.d.ts +12 -0
  223. package/dist/agents/52-offline-mode-tester.d.ts.map +1 -0
  224. package/dist/agents/52-offline-mode-tester.js +161 -0
  225. package/dist/agents/52-offline-mode-tester.js.map +1 -0
  226. package/dist/agents/53-graceful-degradation-tester.d.ts +12 -0
  227. package/dist/agents/53-graceful-degradation-tester.d.ts.map +1 -0
  228. package/dist/agents/53-graceful-degradation-tester.js +130 -0
  229. package/dist/agents/53-graceful-degradation-tester.js.map +1 -0
  230. package/dist/agents/54-websocket-tester.d.ts +10 -0
  231. package/dist/agents/54-websocket-tester.d.ts.map +1 -0
  232. package/dist/agents/54-websocket-tester.js +132 -0
  233. package/dist/agents/54-websocket-tester.js.map +1 -0
  234. package/dist/agents/55-realtime-sync-tester.d.ts +11 -0
  235. package/dist/agents/55-realtime-sync-tester.d.ts.map +1 -0
  236. package/dist/agents/55-realtime-sync-tester.js +175 -0
  237. package/dist/agents/55-realtime-sync-tester.js.map +1 -0
  238. package/dist/agents/56-file-upload-tester.d.ts +12 -0
  239. package/dist/agents/56-file-upload-tester.d.ts.map +1 -0
  240. package/dist/agents/56-file-upload-tester.js +166 -0
  241. package/dist/agents/56-file-upload-tester.js.map +1 -0
  242. package/dist/agents/57-export-tester.d.ts +11 -0
  243. package/dist/agents/57-export-tester.d.ts.map +1 -0
  244. package/dist/agents/57-export-tester.js +155 -0
  245. package/dist/agents/57-export-tester.js.map +1 -0
  246. package/dist/agents/58-payment-flow-tester.d.ts +11 -0
  247. package/dist/agents/58-payment-flow-tester.d.ts.map +1 -0
  248. package/dist/agents/58-payment-flow-tester.js +159 -0
  249. package/dist/agents/58-payment-flow-tester.js.map +1 -0
  250. package/dist/agents/59-ssl-tls-auditor.d.ts +10 -0
  251. package/dist/agents/59-ssl-tls-auditor.d.ts.map +1 -0
  252. package/dist/agents/59-ssl-tls-auditor.js +132 -0
  253. package/dist/agents/59-ssl-tls-auditor.js.map +1 -0
  254. package/dist/agents/60-dns-cdn-tester.d.ts +10 -0
  255. package/dist/agents/60-dns-cdn-tester.d.ts.map +1 -0
  256. package/dist/agents/60-dns-cdn-tester.js +105 -0
  257. package/dist/agents/60-dns-cdn-tester.js.map +1 -0
  258. package/dist/agents/61-docker-health-checker.d.ts +10 -0
  259. package/dist/agents/61-docker-health-checker.d.ts.map +1 -0
  260. package/dist/agents/61-docker-health-checker.js +95 -0
  261. package/dist/agents/61-docker-health-checker.js.map +1 -0
  262. package/dist/agents/62-env-config-validator.d.ts +10 -0
  263. package/dist/agents/62-env-config-validator.d.ts.map +1 -0
  264. package/dist/agents/62-env-config-validator.js +132 -0
  265. package/dist/agents/62-env-config-validator.js.map +1 -0
  266. package/dist/agents/63-log-quality-auditor.d.ts +9 -0
  267. package/dist/agents/63-log-quality-auditor.d.ts.map +1 -0
  268. package/dist/agents/63-log-quality-auditor.js +121 -0
  269. package/dist/agents/63-log-quality-auditor.js.map +1 -0
  270. package/dist/agents/64-analytics-tracker-tester.d.ts +10 -0
  271. package/dist/agents/64-analytics-tracker-tester.d.ts.map +1 -0
  272. package/dist/agents/64-analytics-tracker-tester.js +146 -0
  273. package/dist/agents/64-analytics-tracker-tester.js.map +1 -0
  274. package/dist/agents/65-gdpr-compliance-tester.d.ts +13 -0
  275. package/dist/agents/65-gdpr-compliance-tester.d.ts.map +1 -0
  276. package/dist/agents/65-gdpr-compliance-tester.js +186 -0
  277. package/dist/agents/65-gdpr-compliance-tester.js.map +1 -0
  278. package/dist/agents/66-soc2-control-validator.d.ts +14 -0
  279. package/dist/agents/66-soc2-control-validator.d.ts.map +1 -0
  280. package/dist/agents/66-soc2-control-validator.js +178 -0
  281. package/dist/agents/66-soc2-control-validator.js.map +1 -0
  282. package/dist/agents/67-wcag-aaa-tester.d.ts +13 -0
  283. package/dist/agents/67-wcag-aaa-tester.d.ts.map +1 -0
  284. package/dist/agents/67-wcag-aaa-tester.js +207 -0
  285. package/dist/agents/67-wcag-aaa-tester.js.map +1 -0
  286. package/dist/agents/68-dead-code-detector.d.ts +9 -0
  287. package/dist/agents/68-dead-code-detector.d.ts.map +1 -0
  288. package/dist/agents/68-dead-code-detector.js +116 -0
  289. package/dist/agents/68-dead-code-detector.js.map +1 -0
  290. package/dist/agents/69-type-safety-auditor.d.ts +9 -0
  291. package/dist/agents/69-type-safety-auditor.d.ts.map +1 -0
  292. package/dist/agents/69-type-safety-auditor.js +148 -0
  293. package/dist/agents/69-type-safety-auditor.js.map +1 -0
  294. package/dist/agents/70-complexity-analyzer.d.ts +10 -0
  295. package/dist/agents/70-complexity-analyzer.d.ts.map +1 -0
  296. package/dist/agents/70-complexity-analyzer.js +154 -0
  297. package/dist/agents/70-complexity-analyzer.js.map +1 -0
  298. package/dist/agents/base-agent.d.ts +3 -1
  299. package/dist/agents/base-agent.d.ts.map +1 -1
  300. package/dist/agents/base-agent.js +7 -1
  301. package/dist/agents/base-agent.js.map +1 -1
  302. package/dist/agents/registry.d.ts +5 -4
  303. package/dist/agents/registry.d.ts.map +1 -1
  304. package/dist/agents/registry.js +170 -29
  305. package/dist/agents/registry.js.map +1 -1
  306. package/dist/clients/agent-mvp.d.ts +66 -0
  307. package/dist/clients/agent-mvp.d.ts.map +1 -0
  308. package/dist/clients/agent-mvp.js +91 -0
  309. package/dist/clients/agent-mvp.js.map +1 -0
  310. package/dist/clients/total-recall.d.ts +37 -0
  311. package/dist/clients/total-recall.d.ts.map +1 -0
  312. package/dist/clients/total-recall.js +224 -0
  313. package/dist/clients/total-recall.js.map +1 -0
  314. package/dist/core/cli.d.ts +3 -0
  315. package/dist/core/cli.d.ts.map +1 -1
  316. package/dist/core/cli.js +122 -6
  317. package/dist/core/cli.js.map +1 -1
  318. package/dist/core/license.js +2 -5
  319. package/dist/core/license.js.map +1 -1
  320. package/dist/core/orchestrator.d.ts +10 -1
  321. package/dist/core/orchestrator.d.ts.map +1 -1
  322. package/dist/core/orchestrator.js +66 -5
  323. package/dist/core/orchestrator.js.map +1 -1
  324. package/package.json +2 -2
@@ -0,0 +1,164 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import type { Finding } from '../core/types';
4
+ import { BaseAgent } from './base-agent';
5
+
6
+ /** Find all .ts files under a directory (excluding tests and node_modules). */
7
+ function findTsFiles(dir: string, results: string[] = []): string[] {
8
+ if (!fs.existsSync(dir)) return results;
9
+
10
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
11
+ for (const entry of entries) {
12
+ const fullPath = path.join(dir, entry.name);
13
+ if (entry.isDirectory() && entry.name !== 'node_modules' && entry.name !== '.git' && entry.name !== 'dist') {
14
+ findTsFiles(fullPath, results);
15
+ } else if (entry.isFile() && entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) {
16
+ results.push(fullPath);
17
+ }
18
+ }
19
+ return results;
20
+ }
21
+
22
+ export class TypeSafetyAuditorAgent extends BaseAgent {
23
+ readonly agentId = 69;
24
+ readonly agentName = 'Type Safety Auditor';
25
+
26
+ protected async preFlight(): Promise<void> {
27
+ // File-based agent
28
+ }
29
+
30
+ protected async execute(): Promise<Finding[]> {
31
+ const findings: Finding[] = [];
32
+
33
+ const projectRoot = this.config.projectRoot ?? process.cwd();
34
+ const srcDir = path.join(projectRoot, 'src');
35
+
36
+ if (!fs.existsSync(srcDir)) {
37
+ findings.push({
38
+ id: `${this.agentId}-no-src-dir`,
39
+ type: 'infra-issue',
40
+ severity: 'low',
41
+ agentId: this.agentId,
42
+ module: 'type-safety-auditor',
43
+ description: 'No src/ directory found in project root',
44
+ });
45
+ return findings;
46
+ }
47
+
48
+ const tsFiles = findTsFiles(srcDir);
49
+ let anyCount = 0;
50
+ let tsIgnoreCount = 0;
51
+ let asAnyCount = 0;
52
+ let missingReturnTypeCount = 0;
53
+
54
+ for (const filePath of tsFiles) {
55
+ const content = fs.readFileSync(filePath, 'utf-8');
56
+ const lines = content.split('\n');
57
+ const relPath = path.relative(projectRoot, filePath);
58
+
59
+ for (let lineNum = 0; lineNum < lines.length; lineNum++) {
60
+ const line = lines[lineNum];
61
+
62
+ // Check for : any (type annotation)
63
+ if (/:\s*any[^a-zA-Z]/.test(line) || /:\s*any\s*$/.test(line)) {
64
+ anyCount++;
65
+ if (anyCount <= 5) {
66
+ findings.push({
67
+ id: `${this.agentId}-any-type-${anyCount}`,
68
+ type: 'test-bug',
69
+ severity: 'low',
70
+ agentId: this.agentId,
71
+ module: 'type-safety-auditor',
72
+ file: filePath,
73
+ line: lineNum + 1,
74
+ description: `"any" type annotation in ${relPath}:${lineNum + 1}`,
75
+ });
76
+ }
77
+ }
78
+
79
+ // Check for @ts-ignore
80
+ if (/@ts-ignore/.test(line)) {
81
+ tsIgnoreCount++;
82
+ if (tsIgnoreCount <= 3) {
83
+ findings.push({
84
+ id: `${this.agentId}-ts-ignore-${tsIgnoreCount}`,
85
+ type: 'test-bug',
86
+ severity: 'low',
87
+ agentId: this.agentId,
88
+ module: 'type-safety-auditor',
89
+ file: filePath,
90
+ line: lineNum + 1,
91
+ description: `@ts-ignore comment in ${relPath}:${lineNum + 1}`,
92
+ });
93
+ }
94
+ }
95
+
96
+ // Check for "as any"
97
+ if (/as\s+any\b/.test(line)) {
98
+ asAnyCount++;
99
+ if (asAnyCount <= 3) {
100
+ findings.push({
101
+ id: `${this.agentId}-as-any-${asAnyCount}`,
102
+ type: 'test-bug',
103
+ severity: 'low',
104
+ agentId: this.agentId,
105
+ module: 'type-safety-auditor',
106
+ file: filePath,
107
+ line: lineNum + 1,
108
+ description: `"as any" assertion in ${relPath}:${lineNum + 1}`,
109
+ });
110
+ }
111
+ }
112
+
113
+ // Check for missing return types on exported functions
114
+ if (/^export\s+(async\s+)?function\s+\w+\s*\([^)]*\)\s*\{/.test(line.trim())) {
115
+ // No return type annotation before {
116
+ missingReturnTypeCount++;
117
+ if (missingReturnTypeCount <= 3) {
118
+ findings.push({
119
+ id: `${this.agentId}-missing-return-type-${missingReturnTypeCount}`,
120
+ type: 'test-bug',
121
+ severity: 'low',
122
+ agentId: this.agentId,
123
+ module: 'type-safety-auditor',
124
+ file: filePath,
125
+ line: lineNum + 1,
126
+ description: `Exported function missing return type in ${relPath}:${lineNum + 1}`,
127
+ });
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ // Summary findings
134
+ if (anyCount > 5) {
135
+ findings.push({
136
+ id: `${this.agentId}-any-summary`,
137
+ type: 'test-bug',
138
+ severity: 'low',
139
+ agentId: this.agentId,
140
+ module: 'type-safety-auditor',
141
+ description: `${anyCount} total "any" type annotations found (showing first 5)`,
142
+ });
143
+ }
144
+
145
+ if (tsIgnoreCount > 3) {
146
+ findings.push({
147
+ id: `${this.agentId}-ts-ignore-summary`,
148
+ type: 'test-bug',
149
+ severity: 'low',
150
+ agentId: this.agentId,
151
+ module: 'type-safety-auditor',
152
+ description: `${tsIgnoreCount} total @ts-ignore comments found (showing first 3)`,
153
+ });
154
+ }
155
+
156
+ this.addEvidence({
157
+ type: 'log',
158
+ path: '',
159
+ description: `Scanned ${tsFiles.length} files: ${anyCount} any, ${tsIgnoreCount} @ts-ignore, ${asAnyCount} as any, ${missingReturnTypeCount} missing return types`,
160
+ });
161
+
162
+ return findings;
163
+ }
164
+ }
@@ -0,0 +1,179 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import type { Finding } from '../core/types';
4
+ import { BaseAgent } from './base-agent';
5
+
6
+ /** Find all .ts files under a directory (excluding tests and node_modules). */
7
+ function findTsFiles(dir: string, results: string[] = []): string[] {
8
+ if (!fs.existsSync(dir)) return results;
9
+
10
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
11
+ for (const entry of entries) {
12
+ const fullPath = path.join(dir, entry.name);
13
+ if (entry.isDirectory() && entry.name !== 'node_modules' && entry.name !== '.git' && entry.name !== 'dist') {
14
+ findTsFiles(fullPath, results);
15
+ } else if (entry.isFile() && entry.name.endsWith('.ts') && !entry.name.endsWith('.test.ts') && !entry.name.endsWith('.spec.ts') && !entry.name.endsWith('.d.ts')) {
16
+ results.push(fullPath);
17
+ }
18
+ }
19
+ return results;
20
+ }
21
+
22
+ /** Branch keywords for rough cyclomatic complexity. */
23
+ const BRANCH_KEYWORDS = /\b(if|else\s+if|else|switch|case|for|while|do|catch|&&|\|\||\?\?)\b/g;
24
+
25
+ interface FunctionInfo {
26
+ name: string;
27
+ startLine: number;
28
+ branchCount: number;
29
+ }
30
+
31
+ export class ComplexityAnalyzerAgent extends BaseAgent {
32
+ readonly agentId = 70;
33
+ readonly agentName = 'Complexity Analyzer';
34
+
35
+ protected async preFlight(): Promise<void> {
36
+ // File-based agent
37
+ }
38
+
39
+ protected async execute(): Promise<Finding[]> {
40
+ const findings: Finding[] = [];
41
+
42
+ const projectRoot = this.config.projectRoot ?? process.cwd();
43
+ const srcDir = path.join(projectRoot, 'src');
44
+
45
+ if (!fs.existsSync(srcDir)) {
46
+ findings.push({
47
+ id: `${this.agentId}-no-src-dir`,
48
+ type: 'infra-issue',
49
+ severity: 'low',
50
+ agentId: this.agentId,
51
+ module: 'complexity-analyzer',
52
+ description: 'No src/ directory found in project root',
53
+ });
54
+ return findings;
55
+ }
56
+
57
+ const tsFiles = findTsFiles(srcDir);
58
+ let complexFunctionCount = 0;
59
+ let longFileCount = 0;
60
+
61
+ for (const filePath of tsFiles) {
62
+ const content = fs.readFileSync(filePath, 'utf-8');
63
+ const lines = content.split('\n');
64
+ const relPath = path.relative(projectRoot, filePath);
65
+
66
+ // Check file length
67
+ if (lines.length > 1000) {
68
+ findings.push({
69
+ id: `${this.agentId}-very-long-file-${longFileCount}`,
70
+ type: 'test-bug',
71
+ severity: 'medium',
72
+ agentId: this.agentId,
73
+ module: 'complexity-analyzer',
74
+ file: filePath,
75
+ description: `File ${relPath} has ${lines.length} lines (>1000) — consider splitting`,
76
+ });
77
+ longFileCount++;
78
+ } else if (lines.length > 500) {
79
+ findings.push({
80
+ id: `${this.agentId}-long-file-${longFileCount}`,
81
+ type: 'test-bug',
82
+ severity: 'low',
83
+ agentId: this.agentId,
84
+ module: 'complexity-analyzer',
85
+ file: filePath,
86
+ description: `File ${relPath} has ${lines.length} lines (>500) — consider refactoring`,
87
+ });
88
+ longFileCount++;
89
+ }
90
+
91
+ // Analyze function complexity
92
+ const functions = this.extractFunctions(lines);
93
+ for (const fn of functions) {
94
+ if (fn.branchCount > 15) {
95
+ complexFunctionCount++;
96
+ if (complexFunctionCount <= 10) {
97
+ findings.push({
98
+ id: `${this.agentId}-complex-function-${complexFunctionCount}`,
99
+ type: 'test-bug',
100
+ severity: 'medium',
101
+ agentId: this.agentId,
102
+ module: 'complexity-analyzer',
103
+ file: filePath,
104
+ line: fn.startLine,
105
+ description: `Function "${fn.name}" in ${relPath}:${fn.startLine} has ${fn.branchCount} branches (>15) — high cyclomatic complexity`,
106
+ suggestedFix: 'Refactor into smaller functions with single responsibilities',
107
+ });
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ if (complexFunctionCount > 10) {
114
+ findings.push({
115
+ id: `${this.agentId}-complex-functions-summary`,
116
+ type: 'test-bug',
117
+ severity: 'medium',
118
+ agentId: this.agentId,
119
+ module: 'complexity-analyzer',
120
+ description: `${complexFunctionCount} functions with high complexity found (showing first 10)`,
121
+ });
122
+ }
123
+
124
+ this.addEvidence({
125
+ type: 'log',
126
+ path: '',
127
+ description: `Scanned ${tsFiles.length} files: ${complexFunctionCount} complex functions, ${longFileCount} long files`,
128
+ });
129
+
130
+ return findings;
131
+ }
132
+
133
+ private extractFunctions(lines: string[]): FunctionInfo[] {
134
+ const functions: FunctionInfo[] = [];
135
+ let currentFunction: FunctionInfo | null = null;
136
+ let braceDepth = 0;
137
+ let functionBraceStart = 0;
138
+
139
+ for (let i = 0; i < lines.length; i++) {
140
+ const line = lines[i];
141
+ const trimmed = line.trim();
142
+
143
+ // Detect function start
144
+ const funcMatch = trimmed.match(/(?:async\s+)?(?:function\s+(\w+)|(\w+)\s*(?:=|:)\s*(?:async\s+)?(?:\([^)]*\)|[^=]*)=>|(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\s*\{)/);
145
+
146
+ if (funcMatch && !currentFunction) {
147
+ const name = funcMatch[1] ?? funcMatch[2] ?? funcMatch[3] ?? 'anonymous';
148
+ currentFunction = { name, startLine: i + 1, branchCount: 0 };
149
+ functionBraceStart = braceDepth;
150
+ }
151
+
152
+ // Count braces
153
+ for (const ch of line) {
154
+ if (ch === '{') braceDepth++;
155
+ if (ch === '}') braceDepth--;
156
+ }
157
+
158
+ // Count branches in current function
159
+ if (currentFunction) {
160
+ const matches = trimmed.match(BRANCH_KEYWORDS);
161
+ if (matches) {
162
+ currentFunction.branchCount += matches.length;
163
+ }
164
+ }
165
+
166
+ // Function ended
167
+ if (currentFunction && braceDepth <= functionBraceStart) {
168
+ functions.push(currentFunction);
169
+ currentFunction = null;
170
+ }
171
+ }
172
+
173
+ if (currentFunction) {
174
+ functions.push(currentFunction);
175
+ }
176
+
177
+ return functions;
178
+ }
179
+ }
@@ -0,0 +1,274 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import type { ValidatedConfig } from '../../core/config';
3
+ import type { Phase } from '../../core/types';
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Stub config helpers
7
+ // ---------------------------------------------------------------------------
8
+
9
+ function makeConfig(overrides: Partial<ValidatedConfig> = {}): ValidatedConfig {
10
+ return {
11
+ schemaVersion: 1,
12
+ name: 'test',
13
+ auth: {
14
+ loginUrl: 'http://localhost/login',
15
+ credentials: {
16
+ admin: { email: 'admin@test.com', password: 'secret' },
17
+ },
18
+ },
19
+ modules: [
20
+ { id: 'dashboard', route: '/dashboard', sidebarIcon: true },
21
+ ],
22
+ environments: {
23
+ alpha: { baseUrl: 'http://localhost:3000', seed: false },
24
+ },
25
+ portals: [],
26
+ breakpoints: [],
27
+ integrations: [],
28
+ workers: [],
29
+ workflows: [],
30
+ accuracy: { enabled: false, decimalPrecision: 2, currencySymbol: '$', timezone: 'UTC' },
31
+ tenancy: { enabled: false, isolationField: 'firmId', testFirms: [] },
32
+ costBudget: { maxPerRun: 100, maxPerAgent: 10, alertThreshold: 0.8, onExceeded: 'abort' },
33
+ agentClassification: { blocking: [], advisory: [24] },
34
+ thresholds: {
35
+ unitCoverage: { lines: 80, functions: 80, branches: 80, statements: 80 },
36
+ lighthouse: { accessibility: 90, performance: 90, bestPractices: 90, seo: 90 },
37
+ apiResponseTime: 2000,
38
+ bundleSizeLimit: 500000,
39
+ maxConsoleErrors: 0,
40
+ },
41
+ disabledAgents: [],
42
+ disabledAgentSet: new Set<number>(),
43
+ ...overrides,
44
+ };
45
+ }
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // Mock fetch
49
+ // ---------------------------------------------------------------------------
50
+
51
+ const fetchMock = vi.fn();
52
+ vi.stubGlobal('fetch', fetchMock);
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // Mock helpers
56
+ // ---------------------------------------------------------------------------
57
+
58
+ const loginMock = vi.fn().mockResolvedValue(undefined);
59
+
60
+ vi.mock('../../helpers/navigation', () => ({
61
+ login: (...args: unknown[]) => loginMock(...args),
62
+ waitForSectionLoad: vi.fn().mockResolvedValue(undefined),
63
+ navigateToSection: vi.fn().mockResolvedValue(undefined),
64
+ switchPortal: vi.fn().mockResolvedValue(undefined),
65
+ }));
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Mock Playwright
69
+ // ---------------------------------------------------------------------------
70
+
71
+ interface MockLocator {
72
+ count: ReturnType<typeof vi.fn>;
73
+ first: ReturnType<typeof vi.fn>;
74
+ nth: ReturnType<typeof vi.fn>;
75
+ click: ReturnType<typeof vi.fn>;
76
+ fill: ReturnType<typeof vi.fn>;
77
+ innerText: ReturnType<typeof vi.fn>;
78
+ }
79
+
80
+ function makeMockLocator(countVal = 0): MockLocator {
81
+ const locator: MockLocator = {
82
+ count: vi.fn().mockResolvedValue(countVal),
83
+ first: vi.fn(),
84
+ nth: vi.fn(),
85
+ click: vi.fn().mockResolvedValue(undefined),
86
+ fill: vi.fn().mockResolvedValue(undefined),
87
+ innerText: vi.fn().mockResolvedValue('some text'),
88
+ };
89
+ locator.first.mockReturnValue(locator);
90
+ locator.nth.mockReturnValue(locator);
91
+ return locator;
92
+ }
93
+
94
+ interface MockPage {
95
+ close: ReturnType<typeof vi.fn>;
96
+ goto: ReturnType<typeof vi.fn>;
97
+ url: ReturnType<typeof vi.fn>;
98
+ locator: ReturnType<typeof vi.fn>;
99
+ waitForTimeout: ReturnType<typeof vi.fn>;
100
+ }
101
+
102
+ function makeMockPage(): MockPage {
103
+ const defaultLocator = makeMockLocator(0);
104
+ return {
105
+ close: vi.fn().mockResolvedValue(undefined),
106
+ goto: vi.fn().mockResolvedValue(undefined),
107
+ url: vi.fn().mockReturnValue('http://localhost:3000/dashboard'),
108
+ locator: vi.fn().mockReturnValue(defaultLocator),
109
+ waitForTimeout: vi.fn().mockResolvedValue(undefined),
110
+ };
111
+ }
112
+
113
+ let currentMockPage: MockPage;
114
+ let mockBrowser: { newPage: ReturnType<typeof vi.fn>; close: ReturnType<typeof vi.fn> };
115
+
116
+ vi.mock('playwright', async () => ({
117
+ chromium: {
118
+ launch: vi.fn().mockImplementation(async () => mockBrowser),
119
+ },
120
+ }));
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // Dynamic import AFTER mocks are hoisted
124
+ // ---------------------------------------------------------------------------
125
+
126
+ const { SignupOnboardingTesterAgent } = await import('../24-signup-onboarding-tester');
127
+
128
+ function createAgent(
129
+ config: ValidatedConfig = makeConfig(),
130
+ phase: Phase = 'alpha',
131
+ ): InstanceType<typeof SignupOnboardingTesterAgent> {
132
+ return new SignupOnboardingTesterAgent(config, phase, '/tmp/test-run');
133
+ }
134
+
135
+ // ---------------------------------------------------------------------------
136
+ // Tests
137
+ // ---------------------------------------------------------------------------
138
+
139
+ describe('SignupOnboardingTesterAgent', () => {
140
+ beforeEach(() => {
141
+ fetchMock.mockReset().mockResolvedValue({ ok: true, status: 200 });
142
+ loginMock.mockReset().mockResolvedValue(undefined);
143
+
144
+ currentMockPage = makeMockPage();
145
+ mockBrowser = {
146
+ newPage: vi.fn().mockResolvedValue(currentMockPage),
147
+ close: vi.fn().mockResolvedValue(undefined),
148
+ };
149
+ });
150
+
151
+ // Identity
152
+ it('has agentId 24 and correct agentName', () => {
153
+ const agent = createAgent();
154
+ expect(agent.agentId).toBe(24);
155
+ expect(agent.agentName).toBe('Signup & Onboarding Tester');
156
+ });
157
+
158
+ // preFlight succeeds
159
+ it('resolves environment in preFlight without error', async () => {
160
+ const agent = createAgent();
161
+ const result = await agent.run();
162
+ expect(result.findings.every(f => !f.description.includes('preFlight'))).toBe(true);
163
+ });
164
+
165
+ // No credentials
166
+ it('produces medium finding when no credentials configured', async () => {
167
+ const config = makeConfig({
168
+ auth: { loginUrl: 'http://localhost/login', credentials: {} },
169
+ });
170
+ const agent = createAgent(config);
171
+ const result = await agent.run();
172
+
173
+ const noCredsFinding = result.findings.find(f => f.id.includes('no-credentials'));
174
+ expect(noCredsFinding).toBeDefined();
175
+ expect(noCredsFinding!.severity).toBe('medium');
176
+ });
177
+
178
+ // Registration page not found
179
+ it('produces medium finding when no registration page found', async () => {
180
+ // goto resolves but no registration form fields (count=0)
181
+ const agent = createAgent();
182
+ const result = await agent.run();
183
+
184
+ const regFinding = result.findings.find(f => f.id.includes('no-register-page'));
185
+ expect(regFinding).toBeDefined();
186
+ expect(regFinding!.severity).toBe('medium');
187
+ });
188
+
189
+ // Registration page found with fields
190
+ it('detects registration form when email and password fields exist', async () => {
191
+ currentMockPage.locator.mockImplementation((sel: string) => {
192
+ if (sel.includes('email')) return makeMockLocator(1);
193
+ if (sel.includes('password')) return makeMockLocator(1);
194
+ if (sel.includes('name')) return makeMockLocator(1);
195
+ if (sel.includes('submit') || sel.includes('Register') || sel.includes('Sign up')) return makeMockLocator(1);
196
+ return makeMockLocator(0);
197
+ });
198
+
199
+ const agent = createAgent();
200
+ const result = await agent.run();
201
+
202
+ // Should NOT have a "no register page" finding
203
+ const regFinding = result.findings.find(f => f.id.includes('no-register-page'));
204
+ expect(regFinding).toBeUndefined();
205
+ });
206
+
207
+ // Login page missing inputs
208
+ it('produces high finding when login page missing email/password', async () => {
209
+ // All locators return 0 by default — means login page has no inputs
210
+ const agent = createAgent();
211
+ const result = await agent.run();
212
+
213
+ const loginMissing = result.findings.find(f => f.id.includes('login-missing-inputs'));
214
+ expect(loginMissing).toBeDefined();
215
+ expect(loginMissing!.severity).toBe('high');
216
+ });
217
+
218
+ // Login flow stuck
219
+ it('produces medium finding when login stays on login page', async () => {
220
+ currentMockPage.url.mockReturnValue('http://localhost:3000/login');
221
+
222
+ const agent = createAgent();
223
+ const result = await agent.run();
224
+
225
+ const stuckFinding = result.findings.find(f => f.id.includes('login-flow-stuck'));
226
+ expect(stuckFinding).toBeDefined();
227
+ expect(stuckFinding!.severity).toBe('medium');
228
+ });
229
+
230
+ // Onboarding detection
231
+ it('reports info finding about onboarding detection', async () => {
232
+ const agent = createAgent();
233
+ const result = await agent.run();
234
+
235
+ const onboardFinding = result.findings.find(
236
+ f => f.id.includes('onboarding-detected') || f.id.includes('no-onboarding'),
237
+ );
238
+ expect(onboardFinding).toBeDefined();
239
+ expect(onboardFinding!.severity).toBe('info');
240
+ });
241
+
242
+ // Playwright crash
243
+ it('produces medium finding when Playwright crashes', async () => {
244
+ mockBrowser.newPage.mockRejectedValue(new Error('Browser crashed'));
245
+
246
+ const agent = createAgent();
247
+ const result = await agent.run();
248
+
249
+ const pwFinding = result.findings.find(f => f.id.includes('playwright-failure'));
250
+ expect(pwFinding).toBeDefined();
251
+ expect(pwFinding!.severity).toBe('medium');
252
+ });
253
+
254
+ // Browser closed in finally
255
+ it('closes browser even when an error occurs', async () => {
256
+ mockBrowser.newPage.mockRejectedValue(new Error('Launch error'));
257
+
258
+ const agent = createAgent();
259
+ await agent.run();
260
+
261
+ expect(mockBrowser.close).toHaveBeenCalled();
262
+ });
263
+
264
+ // Login flow error
265
+ it('handles login flow navigation errors gracefully', async () => {
266
+ currentMockPage.goto.mockRejectedValue(new Error('Navigation error'));
267
+
268
+ const agent = createAgent();
269
+ const result = await agent.run();
270
+
271
+ // Should have a navigation-related finding but not crash
272
+ expect(result.status).toBeDefined();
273
+ });
274
+ });