quality-intelligence-engine 2.2.3 → 2.2.4

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 (257) hide show
  1. package/.github/workflows/playwright.yml +27 -0
  2. package/.github/workflows/quality-intelligence.yml +45 -0
  3. package/CHANGELOG.md +164 -0
  4. package/REFACTORING_SUMMARY.md +417 -0
  5. package/artifacts/failure-analysis/run-1769595909824-login_with_valid_user.md +25 -0
  6. package/artifacts/failure-analysis/run-1769596445203-login_with_valid_user.md +25 -0
  7. package/artifacts/failure-analysis/run-1769596573162-login_with_valid_user.md +34 -0
  8. package/artifacts/failure-analysis/run-1769596591727-login_with_valid_user.md +25 -0
  9. package/artifacts/failure-analysis/run-1769596600117-login_with_valid_user.md +34 -0
  10. package/artifacts/failure-analysis/run-1769596782107-login_with_valid_user.md +32 -0
  11. package/artifacts/failure-analysis/run-1769596940770-login_with_valid_user.md +28 -0
  12. package/artifacts/failure-analysis/run-1769596960417-login_with_valid_user.md +28 -0
  13. package/artifacts/failure-analysis/run-1769596981303-login_with_valid_user.md +28 -0
  14. package/artifacts/failure-analysis/run-1769597351831-login_with_valid_user.md +21 -0
  15. package/artifacts/failure-analysis/run-1769597486816-login_with_valid_user.md +21 -0
  16. package/artifacts/failure-analysis/run-1769599708378-login_with_valid_user.md +22 -0
  17. package/artifacts/failure-analysis/run-1769600327960-login_with_valid_user.md +22 -0
  18. package/artifacts/failure-analysis/run-1769600596201-saucedemo__login_fails_with_wrong_password_fail.md +22 -0
  19. package/artifacts/failure-analysis/run-1769600682675-saucedemo__login_fails_with_wrong_password_fail.md +22 -0
  20. package/artifacts/failure-analysis/run-1769602090701-saucedemo__add_to_cart_button_is_hidden_fail.md +30 -0
  21. package/artifacts/failure-analysis/run-1769602090701-saucedemo__cart_count_updates_to_2_after_adding_one_item_fail.md +30 -0
  22. package/artifacts/failure-analysis/run-1769602090701-saucedemo__checkout_navigates_to_payment_page_directly_fail.md +30 -0
  23. package/artifacts/failure-analysis/run-1769602090701-saucedemo__inventory_shows_10_products_fail.md +30 -0
  24. package/artifacts/failure-analysis/run-1769602090701-saucedemo__products_sorted_high_to_low_start_with_999_fail.md +30 -0
  25. package/artifacts/failure-history/1769696674298.json +9 -0
  26. package/artifacts/failure-history/1769697768622.json +10 -0
  27. package/artifacts/failure-history/1769697923557.json +10 -0
  28. package/artifacts/failure-history/1769698160213.json +11 -0
  29. package/artifacts/failure-history/1769698353440.json +11 -0
  30. package/artifacts/failure-history/1769698763306.json +11 -0
  31. package/artifacts/failure-history/1769698878947.json +11 -0
  32. package/artifacts/failure-history/1769699909817.json +11 -0
  33. package/artifacts/failure-history/1769703130913.json +11 -0
  34. package/artifacts/failure-history/1769703142113.json +11 -0
  35. package/artifacts/failure-history/1769703158978.json +11 -0
  36. package/artifacts/failure-history/1769703406025.json +11 -0
  37. package/artifacts/failure-history/1769703422720.json +11 -0
  38. package/artifacts/failure-history/1769703518837.json +11 -0
  39. package/artifacts/failure-history/1769703530419.json +11 -0
  40. package/artifacts/failure-history/1769703577078.json +11 -0
  41. package/artifacts/failure-history/1769704067098.json +11 -0
  42. package/artifacts/failure-history/1769704074618.json +11 -0
  43. package/artifacts/failure-history/1769704084948.json +11 -0
  44. package/artifacts/failure-history/1769704091950.json +11 -0
  45. package/artifacts/failure-history/1769704435355.json +11 -0
  46. package/artifacts/failure-history/1769704832871.json +11 -0
  47. package/artifacts/failure-history/1769707051830.json +11 -0
  48. package/artifacts/failure-history/1769739820395.json +11 -0
  49. package/artifacts/failure-history/1769739820400.json +11 -0
  50. package/artifacts/failure-history/1769742422254.json +11 -0
  51. package/artifacts/failure-history/1769743106016.json +11 -0
  52. package/artifacts/failure-history/1769743121857.json +11 -0
  53. package/artifacts/failure-history/1769750875212.json +11 -0
  54. package/artifacts/failure-history/1769750880790.json +11 -0
  55. package/artifacts/failure-history/1769761177923.json +11 -0
  56. package/artifacts/failure-history/1769761191176.json +11 -0
  57. package/bin/qi.ts +37 -0
  58. package/config/agent.config.json +18 -0
  59. package/data/failures/fingerprints/0ded7b45.json +10 -0
  60. package/data/failures/fingerprints/2437666a.json +8 -0
  61. package/data/failures/fingerprints/3746e3b4.json +42 -0
  62. package/data/failures/fingerprints/533e258f.json +10 -0
  63. package/data/failures/fingerprints/56b547d3.json +10 -0
  64. package/data/failures/fingerprints/693661fa.json +10 -0
  65. package/data/failures/fingerprints/789126b1.json +8 -0
  66. package/data/failures/fingerprints/936d995e.json +10 -0
  67. package/data/failures/fingerprints/ba5f6c0a.json +10 -0
  68. package/data/failures/fingerprints/f148a261.json +56 -0
  69. package/data/failures/fingerprints/fa14440f.json +14 -0
  70. package/data/failures/registry.json +57 -0
  71. package/data/flakiness/history.json +71 -0
  72. package/dist/bin/qi.js +0 -0
  73. package/dist/src/intelligence/failure-fingerprinting/failure.classifier.js +5 -1
  74. package/dist/src/intelligence/failure-fingerprinting/failure.tracker.js +5 -0
  75. package/dist/src/playwright/qi.reporter.js +17 -0
  76. package/final.sanity.test.ts +46 -0
  77. package/input/raw-failure.json +36 -0
  78. package/input/raw-pass.json +33 -0
  79. package/output/run-2026-01-28_02-48-38-420/BACKEND_API_FAILURE-AuthController.java-/users/{id}/analysis.md +50 -0
  80. package/output/run-2026-01-28_02-48-38-420/TEST_FAILURE-Unknown--/analysis.md +50 -0
  81. package/output/run-2026-01-28_02-48-52-140/BACKEND_API_FAILURE-AuthController.java-/users/{id}/analysis.md +50 -0
  82. package/output/run-2026-01-28_02-48-52-140/TEST_FAILURE-Unknown--/analysis.md +50 -0
  83. package/output/run-2026-01-28_03-13-16-302/BACKEND_API_FAILURE-AuthController.java-/users/{id}/analysis.md +50 -0
  84. package/output/run-2026-01-28_03-13-16-302/PASS-checkout.spec.ts-API_WARNING/analysis.md +49 -0
  85. package/output/run-2026-01-28_03-13-16-302/PASS-login.spec.ts-FLAKY_PASS/analysis.md +49 -0
  86. package/output/run-2026-01-28_03-13-16-302/TEST_FAILURE-Unknown--/analysis.md +50 -0
  87. package/output/run-2026-01-28_03-29-49-786/BACKEND_API_FAILURE-AuthController.java-/users/{id}/analysis.md +50 -0
  88. package/package.json +4 -10
  89. package/playwright-results/.last-run.json +17 -0
  90. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium/error-context.md +31 -0
  91. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium/test-failed-1.png +0 -0
  92. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium/trace.zip +0 -0
  93. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium/video.webm +0 -0
  94. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium-retry1/error-context.md +31 -0
  95. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium-retry1/test-failed-1.png +0 -0
  96. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium-retry1/trace.zip +0 -0
  97. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--chromium-retry1/video.webm +0 -0
  98. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox/error-context.md +31 -0
  99. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox/test-failed-1.png +0 -0
  100. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox/trace.zip +0 -0
  101. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox/video.webm +0 -0
  102. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox-retry1/error-context.md +31 -0
  103. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox-retry1/test-failed-1.png +0 -0
  104. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox-retry1/trace.zip +0 -0
  105. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--firefox-retry1/video.webm +0 -0
  106. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit/error-context.md +31 -0
  107. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit/test-failed-1.png +0 -0
  108. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit/trace.zip +0 -0
  109. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit/video.webm +0 -0
  110. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit-retry1/error-context.md +31 -0
  111. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit-retry1/test-failed-1.png +0 -0
  112. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit-retry1/trace.zip +0 -0
  113. package/playwright-results/saucedemo-email-like-valid-d5dc6-rname-format-rejected-FAIL--webkit-retry1/video.webm +0 -0
  114. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium/error-context.md +112 -0
  115. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium/test-failed-1.png +0 -0
  116. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium/trace.zip +0 -0
  117. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium/video.webm +0 -0
  118. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium-retry1/error-context.md +112 -0
  119. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium-retry1/test-failed-1.png +0 -0
  120. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium-retry1/trace.zip +0 -0
  121. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--chromium-retry1/video.webm +0 -0
  122. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox/error-context.md +112 -0
  123. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox/test-failed-1.png +0 -0
  124. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox/trace.zip +0 -0
  125. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox/video.webm +0 -0
  126. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox-retry1/error-context.md +112 -0
  127. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox-retry1/test-failed-1.png +0 -0
  128. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox-retry1/trace.zip +0 -0
  129. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--firefox-retry1/video.webm +0 -0
  130. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit/error-context.md +112 -0
  131. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit/test-failed-1.png +0 -0
  132. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit/trace.zip +0 -0
  133. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit/video.webm +0 -0
  134. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit-retry1/error-context.md +112 -0
  135. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit-retry1/test-failed-1.png +0 -0
  136. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit-retry1/trace.zip +0 -0
  137. package/playwright-results/saucedemo-numeric-mismatch-7c4f3-to-cart-button-hidden-FAIL--webkit-retry1/video.webm +0 -0
  138. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium/error-context.md +112 -0
  139. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium/test-failed-1.png +0 -0
  140. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium/trace.zip +0 -0
  141. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium/video.webm +0 -0
  142. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium-retry1/error-context.md +112 -0
  143. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium-retry1/test-failed-1.png +0 -0
  144. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium-retry1/trace.zip +0 -0
  145. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--chromium-retry1/video.webm +0 -0
  146. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox/error-context.md +112 -0
  147. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox/test-failed-1.png +0 -0
  148. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox/trace.zip +0 -0
  149. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox/video.webm +0 -0
  150. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox-retry1/error-context.md +112 -0
  151. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox-retry1/test-failed-1.png +0 -0
  152. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox-retry1/trace.zip +0 -0
  153. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--firefox-retry1/video.webm +0 -0
  154. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit/error-context.md +112 -0
  155. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit/test-failed-1.png +0 -0
  156. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit/trace.zip +0 -0
  157. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit/video.webm +0 -0
  158. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit-retry1/error-context.md +112 -0
  159. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit-retry1/test-failed-1.png +0 -0
  160. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit-retry1/trace.zip +0 -0
  161. package/playwright-results/saucedemo-numeric-mismatch-cd423-entory-count-mismatch-FAIL--webkit-retry1/video.webm +0 -0
  162. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium/error-context.md +31 -0
  163. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium/test-failed-1.png +0 -0
  164. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium/trace.zip +0 -0
  165. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium/video.webm +0 -0
  166. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium-retry1/error-context.md +31 -0
  167. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium-retry1/test-failed-1.png +0 -0
  168. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium-retry1/trace.zip +0 -0
  169. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--chromium-retry1/video.webm +0 -0
  170. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox/error-context.md +31 -0
  171. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox/test-failed-1.png +0 -0
  172. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox/trace.zip +0 -0
  173. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox/video.webm +0 -0
  174. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox-retry1/error-context.md +31 -0
  175. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox-retry1/test-failed-1.png +0 -0
  176. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox-retry1/trace.zip +0 -0
  177. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--firefox-retry1/video.webm +0 -0
  178. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit/error-context.md +31 -0
  179. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit/test-failed-1.png +0 -0
  180. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit/trace.zip +0 -0
  181. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit/video.webm +0 -0
  182. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit-retry1/error-context.md +31 -0
  183. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit-retry1/test-failed-1.png +0 -0
  184. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit-retry1/trace.zip +0 -0
  185. package/playwright-results/saucedemo-numeric-mismatch-f085e-E-unauthorized-access-FAIL--webkit-retry1/video.webm +0 -0
  186. package/playwright.config.ts +42 -0
  187. package/quality-intelligence-engine-2.2.0.tgz +0 -0
  188. package/quality-intelligence-engine-2.2.2.tgz +0 -0
  189. package/sanity.test.ts +33 -0
  190. package/src/adapters/playwright-folder.adapter.ts +85 -0
  191. package/src/adapters/playwright-json.adapter.ts +49 -0
  192. package/src/adapters/playwright.adapter.ts +44 -0
  193. package/src/cli/qi-test.ts +20 -0
  194. package/src/cli/qi.ts +67 -0
  195. package/src/cli/ui/divider.ts +9 -0
  196. package/src/cli/ui/failureLogger.ts +33 -0
  197. package/src/configLoader.ts +70 -0
  198. package/src/console/issue-view.ts +193 -0
  199. package/src/failure-analysis/failure-analyzer.ts +43 -0
  200. package/src/final-run.ts +174 -0
  201. package/src/final-runner.ts +31 -0
  202. package/src/fixtures/networkCollector.ts +27 -0
  203. package/src/history/failure-history.store.ts +23 -0
  204. package/src/history/failure-history.types.ts +12 -0
  205. package/src/history/failure-trend.analyzer.ts +49 -0
  206. package/src/index.ts +10 -0
  207. package/src/integrations/ci/ci-annotator.ts +42 -0
  208. package/src/intelligence/confidence-calibration.engine.ts +41 -0
  209. package/src/intelligence/decision-intelligence/confidence.engine.ts +18 -0
  210. package/src/intelligence/decision-intelligence/decision.config.ts +18 -0
  211. package/src/intelligence/decision-intelligence/decision.engine.ts +30 -0
  212. package/src/intelligence/decision-intelligence/decision.types.ts +15 -0
  213. package/src/intelligence/failure-fingerprinting/failure.classifier.ts +61 -0
  214. package/src/intelligence/failure-fingerprinting/failure.store.ts +42 -0
  215. package/src/intelligence/failure-fingerprinting/failure.tracker.ts +28 -0
  216. package/src/intelligence/failure-fingerprinting/fingerprint.generator.ts +28 -0
  217. package/src/intelligence/failure-fingerprinting/fingerprint.types.ts +14 -0
  218. package/src/intelligence/flakiness-intelligence/flakiness.analyzer.ts +23 -0
  219. package/src/intelligence/flakiness-intelligence/flakiness.fingerprint.ts +14 -0
  220. package/src/intelligence/flakiness-intelligence/flakiness.store.ts +24 -0
  221. package/src/intelligence/flakiness-intelligence/flakiness.tracker.ts +42 -0
  222. package/src/intelligence/flakiness-intelligence/flakiness.types.ts +8 -0
  223. package/src/intelligence/intelligence.pipeline.ts +20 -0
  224. package/src/intelligence/llm-explainer.ts +29 -0
  225. package/src/intelligence/root-cause/rootcause.engine.ts +46 -0
  226. package/src/intelligence/trend-intelligence/trend.engine.ts +42 -0
  227. package/src/markdownWriter.ts +68 -0
  228. package/src/normalizer.ts +31 -0
  229. package/src/passAnalyzer.ts +38 -0
  230. package/src/pipeline/ai.summarizer.ts +39 -0
  231. package/src/pipeline/failure-analysis.pipeline.ts +13 -0
  232. package/src/pipeline/failure-grouping.pipeline.ts +67 -0
  233. package/src/playwright/qi.reporter.ts +26 -0
  234. package/src/reporter.ts +88 -0
  235. package/src/reporters/qi-reporter.js +34 -0
  236. package/src/rules.ts +35 -0
  237. package/src/runManager.ts +21 -0
  238. package/src/runner.ts +12 -0
  239. package/src/runtime/networkCollector.ts +36 -0
  240. package/src/stackParser.ts +22 -0
  241. package/src/test-run.ts +59 -0
  242. package/src/types/analysis-result.ts +16 -0
  243. package/src/types/failure.types.ts +28 -0
  244. package/src/types/playwright-failure.ts +10 -0
  245. package/src/types.ts +102 -0
  246. package/src/utils/artifact.locator.ts +42 -0
  247. package/src/utils/confidence-constants.ts +111 -0
  248. package/src/utils/file-utils.ts +146 -0
  249. package/src/v2/llm/llm-advisor.ts +22 -0
  250. package/src/v2/pipeline/v2-intelligence.pipeline.ts +21 -0
  251. package/src/v2/self-healing/self-healer.ts +60 -0
  252. package/src/v2/trace-intelligence/trace-analyzer.ts +42 -0
  253. package/src/v2-test-run.ts +74 -0
  254. package/tests/fixtures.ts +40 -0
  255. package/tests/saucedemo-login-validation.spec.ts +74 -0
  256. package/tsconfig.json +16 -0
  257. package/tsconfig.playwright.json +13 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Confidence Calculation Constants
3
+ *
4
+ * These constants define the base confidence levels and adjustments
5
+ * used throughout the quality intelligence engine.
6
+ */
7
+
8
+ /**
9
+ * Base confidence levels for different error types
10
+ */
11
+ export const BASE_CONFIDENCE = {
12
+ /** Strong backend failure signal (5xx errors) */
13
+ BACKEND_SERVER_ERROR: 0.95,
14
+
15
+ /** Backend API failure (any API error) */
16
+ BACKEND_API_ERROR: 0.9,
17
+
18
+ /** Test or automation failure */
19
+ TEST_ERROR: 0.75,
20
+
21
+ /** Unknown or weak signal */
22
+ UNKNOWN: 0.6,
23
+ } as const;
24
+
25
+ /**
26
+ * Confidence adjustments based on test context and signals
27
+ */
28
+ export const CONFIDENCE_ADJUSTMENTS = {
29
+ /** UI successfully rendered and reached assertion */
30
+ UI_RENDERED: 0.05,
31
+
32
+ /** Test involves authentication or login flow */
33
+ AUTH_FLOW_DETECTED: 0.05,
34
+
35
+ /** Explicit authentication failure detected */
36
+ EXPLICIT_AUTH_FAILURE: 0.1,
37
+
38
+ /** Test involves inventory or data operations */
39
+ DATA_OPERATION_DETECTED: 0.05,
40
+
41
+ /** Numeric mismatch detected in assertions */
42
+ NUMERIC_MISMATCH: 0.05,
43
+ } as const;
44
+
45
+ /**
46
+ * Maximum and minimum confidence bounds
47
+ */
48
+ export const CONFIDENCE_BOUNDS = {
49
+ /** Maximum confidence score (never 100% certain) */
50
+ MAX: 0.95,
51
+
52
+ /** Minimum confidence score for reporting */
53
+ MIN: 0.5,
54
+ } as const;
55
+
56
+ /**
57
+ * Confidence thresholds for decision making
58
+ */
59
+ export const CONFIDENCE_THRESHOLDS = {
60
+ /** Threshold for blocking CI/CD (high confidence failure) */
61
+ FAIL: 0.85,
62
+
63
+ /** Threshold for reporting pass risks */
64
+ PASS_RISK: 0.6,
65
+
66
+ /** Threshold for investigating (medium confidence) */
67
+ INVESTIGATE: 0.7,
68
+
69
+ /** Threshold for shipping (high confidence in safety) */
70
+ SHIP: 0.85,
71
+ } as const;
72
+
73
+ /**
74
+ * Taxonomy rule base confidence levels
75
+ */
76
+ export const TAXONOMY_BASE_CONFIDENCE = {
77
+ /** Numeric data mismatch */
78
+ NUMERIC_MISMATCH: 0.6,
79
+
80
+ /** Authentication failure */
81
+ AUTH_FAILURE: 0.7,
82
+
83
+ /** UI visibility issue */
84
+ VISIBILITY: 0.7,
85
+
86
+ /** Network timeout */
87
+ TIMEOUT: 0.65,
88
+
89
+ /** Element not found */
90
+ ELEMENT_NOT_FOUND: 0.7,
91
+
92
+ /** Default fallback */
93
+ DEFAULT: 0.7,
94
+ } as const;
95
+
96
+ /**
97
+ * Helper function to clamp confidence within bounds
98
+ */
99
+ export function clampConfidence(value: number): number {
100
+ return Math.max(
101
+ CONFIDENCE_BOUNDS.MIN,
102
+ Math.min(CONFIDENCE_BOUNDS.MAX, value)
103
+ );
104
+ }
105
+
106
+ /**
107
+ * Helper function to format confidence as percentage string
108
+ */
109
+ export function formatConfidence(value: number): string {
110
+ return `${(value * 100).toFixed(1)}%`;
111
+ }
@@ -0,0 +1,146 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Custom error class for file operations
6
+ */
7
+ export class FileOperationError extends Error {
8
+ constructor(
9
+ message: string,
10
+ public readonly filePath: string,
11
+ public readonly operation: 'read' | 'write' | 'parse',
12
+ public readonly originalError?: Error
13
+ ) {
14
+ super(message);
15
+ this.name = 'FileOperationError';
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Safely read and parse a JSON file with proper error handling
21
+ * @param filePath - Absolute or relative path to the JSON file
22
+ * @returns Parsed JSON object
23
+ * @throws FileOperationError if file cannot be read or parsed
24
+ */
25
+ export function readJsonFile<T>(filePath: string): T {
26
+ try {
27
+ // Check if file exists
28
+ if (!fs.existsSync(filePath)) {
29
+ throw new FileOperationError(
30
+ `File not found: ${filePath}`,
31
+ filePath,
32
+ 'read'
33
+ );
34
+ }
35
+
36
+ // Read file content
37
+ let content: string;
38
+ try {
39
+ content = fs.readFileSync(filePath, 'utf-8');
40
+ } catch (error) {
41
+ throw new FileOperationError(
42
+ `Failed to read file: ${filePath}`,
43
+ filePath,
44
+ 'read',
45
+ error as Error
46
+ );
47
+ }
48
+
49
+ // Parse JSON
50
+ try {
51
+ return JSON.parse(content) as T;
52
+ } catch (error) {
53
+ throw new FileOperationError(
54
+ `Invalid JSON in file: ${filePath}`,
55
+ filePath,
56
+ 'parse',
57
+ error as Error
58
+ );
59
+ }
60
+ } catch (error) {
61
+ if (error instanceof FileOperationError) {
62
+ throw error;
63
+ }
64
+ throw new FileOperationError(
65
+ `Unexpected error reading ${filePath}: ${(error as Error).message}`,
66
+ filePath,
67
+ 'read',
68
+ error as Error
69
+ );
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Safely write JSON to a file with proper error handling
75
+ * @param filePath - Absolute or relative path to the JSON file
76
+ * @param data - Data to write (will be JSON.stringified)
77
+ * @param pretty - Whether to pretty-print the JSON (default: true)
78
+ */
79
+ export function writeJsonFile<T>(
80
+ filePath: string,
81
+ data: T,
82
+ pretty: boolean = true
83
+ ): void {
84
+ try {
85
+ // Ensure directory exists
86
+ const dir = path.dirname(filePath);
87
+ if (!fs.existsSync(dir)) {
88
+ fs.mkdirSync(dir, { recursive: true });
89
+ }
90
+
91
+ // Stringify data
92
+ const content = pretty
93
+ ? JSON.stringify(data, null, 2)
94
+ : JSON.stringify(data);
95
+
96
+ // Write to file
97
+ try {
98
+ fs.writeFileSync(filePath, content, 'utf-8');
99
+ } catch (error) {
100
+ throw new FileOperationError(
101
+ `Failed to write file: ${filePath}`,
102
+ filePath,
103
+ 'write',
104
+ error as Error
105
+ );
106
+ }
107
+ } catch (error) {
108
+ if (error instanceof FileOperationError) {
109
+ throw error;
110
+ }
111
+ throw new FileOperationError(
112
+ `Unexpected error writing ${filePath}: ${(error as Error).message}`,
113
+ filePath,
114
+ 'write',
115
+ error as Error
116
+ );
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Check if a file exists
122
+ * @param filePath - Path to check
123
+ * @returns true if file exists
124
+ */
125
+ export function fileExists(filePath: string): boolean {
126
+ return fs.existsSync(filePath);
127
+ }
128
+
129
+ /**
130
+ * Ensure a directory exists, creating it if necessary
131
+ * @param dirPath - Directory path to ensure
132
+ */
133
+ export function ensureDirectory(dirPath: string): void {
134
+ if (!fs.existsSync(dirPath)) {
135
+ fs.mkdirSync(dirPath, { recursive: true });
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Resolve a path relative to the project root
141
+ * @param relativePath - Path relative to project root
142
+ * @returns Absolute path
143
+ */
144
+ export function resolvePath(...segments: string[]): string {
145
+ return path.join(process.cwd(), ...segments);
146
+ }
@@ -0,0 +1,22 @@
1
+ // src/v2/llm/llm-advisor.ts
2
+
3
+ export interface LLMAdvice {
4
+ summary: string;
5
+ fixRecommendation: string[];
6
+ }
7
+
8
+ /**
9
+ * Stub for ChatGPT / Azure / Local LLM
10
+ */
11
+ export async function getLLMAdvice(
12
+ failureSummary: string
13
+ ): Promise<LLMAdvice> {
14
+ return {
15
+ summary: `AI analysis of failure: ${failureSummary}`,
16
+ fixRecommendation: [
17
+ "Check backend API response",
18
+ "Validate UI rendering timing",
19
+ "Review recent code changes"
20
+ ]
21
+ };
22
+ }
@@ -0,0 +1,21 @@
1
+ // src/v2/pipeline/v2-intelligence.pipeline.ts
2
+
3
+ import { analyzeTrace } from "../trace-intelligence/trace-analyzer";
4
+ import { attemptSelfHeal } from "../self-healing/self-healer";
5
+ import { getLLMAdvice } from "../llm/llm-advisor";
6
+
7
+ export async function runV2Intelligence(
8
+ failureFolder: string,
9
+ failureType: string,
10
+ errorMessage: string
11
+ ) {
12
+ const trace = analyzeTrace(failureFolder);
13
+ const healing = attemptSelfHeal(failureType, errorMessage);
14
+ const llm = await getLLMAdvice(failureType);
15
+
16
+ return {
17
+ trace,
18
+ healing,
19
+ llm
20
+ };
21
+ }
@@ -0,0 +1,60 @@
1
+ // src/v2/self-healing/self-healer.ts
2
+
3
+ export interface HealingSuggestion {
4
+ reason: string;
5
+ suggestedFix: string;
6
+ confidence: number;
7
+ }
8
+
9
+ /**
10
+ * Self-Healing Decision Engine (V2)
11
+ * Decides WHAT can be auto-fixed and WHAT should not
12
+ */
13
+ export function attemptSelfHeal(
14
+ failureType: string,
15
+ errorMessage: string
16
+ ): HealingSuggestion | null {
17
+
18
+ const msg = errorMessage.toLowerCase();
19
+
20
+ // 🔁 Flaky tests
21
+ if (failureType === "FLAKY") {
22
+ return {
23
+ reason: "Intermittent retry-based failure detected",
24
+ suggestedFix: "Add proper waits or retry assertions",
25
+ confidence: 0.6
26
+ };
27
+ }
28
+
29
+ // 🧭 UI / Locator issues
30
+ if (failureType === "UI_STATE" || failureType === "LOCATOR_CHANGED") {
31
+ return {
32
+ reason: "UI element state or locator changed",
33
+ suggestedFix: "Re-locate element using role/text-based selectors",
34
+ confidence: 0.7
35
+ };
36
+ }
37
+
38
+ // 🔢 Numeric mismatch — CONDITIONAL healing
39
+ if (failureType === "NUMERIC_MISMATCH") {
40
+
41
+ // UI-level numeric problems (healable)
42
+ if (
43
+ msg.includes("count") ||
44
+ msg.includes("items") ||
45
+ msg.includes("length") ||
46
+ msg.includes("round")
47
+ ) {
48
+ return {
49
+ reason: "UI count or rounding issue detected",
50
+ suggestedFix: "Update assertion logic or normalize UI values",
51
+ confidence: 0.55
52
+ };
53
+ }
54
+
55
+ // Backend/API numeric issues (DO NOT HEAL)
56
+ return null;
57
+ }
58
+
59
+ return null;
60
+ }
@@ -0,0 +1,42 @@
1
+ // src/v2/trace-intelligence/trace-analyzer.ts
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+
6
+ export interface TraceInsight {
7
+ page: string;
8
+ failureStep: string;
9
+ screenshots: string[];
10
+ traceFile?: string;
11
+ note?: string;
12
+ }
13
+
14
+ export function analyzeTrace(failureFolder: string): TraceInsight {
15
+ const fullPath = path.resolve(failureFolder);
16
+
17
+ if (!fs.existsSync(fullPath)) {
18
+ return {
19
+ page: "UNKNOWN",
20
+ failureStep: "Trace folder not found",
21
+ screenshots: [],
22
+ note: `Missing folder: ${failureFolder}`
23
+ };
24
+ }
25
+
26
+ const files = fs.readdirSync(fullPath);
27
+
28
+ const screenshots = files
29
+ .filter(f => f.endsWith(".png") || f.endsWith(".jpg"))
30
+ .map(f => path.join(fullPath, f));
31
+
32
+ const traceFile = files.includes("trace.zip")
33
+ ? path.join(fullPath, "trace.zip")
34
+ : undefined;
35
+
36
+ return {
37
+ page: "UNKNOWN_PAGE",
38
+ failureStep: "Action before failure",
39
+ screenshots,
40
+ traceFile
41
+ };
42
+ }
@@ -0,0 +1,74 @@
1
+ // src/v2-test-run.ts
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { runV2Intelligence } from "./v2/pipeline/v2-intelligence.pipeline";
6
+
7
+ function pickOneFailureFolder(): string | null {
8
+ const base = "playwright-results";
9
+
10
+ if (!fs.existsSync(base)) return null;
11
+
12
+ const entries = fs.readdirSync(base, { withFileTypes: true });
13
+ const folder = entries.find(e => e.isDirectory());
14
+
15
+ return folder ? path.join(base, folder.name) : null;
16
+ }
17
+
18
+ async function run() {
19
+ const failureFolder = pickOneFailureFolder();
20
+
21
+ if (!failureFolder) {
22
+ console.error("No Playwright failure folders found.");
23
+ return;
24
+ }
25
+
26
+ const result = await runV2Intelligence(
27
+ failureFolder,
28
+ "NUMERIC_MISMATCH",
29
+ "Expected 10, received 6"
30
+ );
31
+
32
+ console.log("==================================================");
33
+ console.log("V2 TRACE INTELLIGENCE OUTPUT");
34
+ console.log("==================================================");
35
+
36
+ console.log(`Failure Folder : ${failureFolder}`);
37
+ console.log(`Failure Type : NUMERIC_MISMATCH`);
38
+
39
+ console.log("\nEvidence:");
40
+ if (result.trace.screenshots.length > 0) {
41
+ console.log(" Screenshots:");
42
+ result.trace.screenshots.forEach(s =>
43
+ console.log(` - ${s}`)
44
+ );
45
+ } else {
46
+ console.log(" Screenshots: none");
47
+ }
48
+
49
+ if (result.trace.traceFile) {
50
+ console.log(` Trace File : ${result.trace.traceFile}`);
51
+ console.log(` Open with : npx playwright show-trace ${result.trace.traceFile}`);
52
+ } else {
53
+ console.log(" Trace File : none");
54
+ }
55
+
56
+ console.log("\nSelf-Healing:");
57
+ if (result.healing) {
58
+ console.log(` Reason : ${result.healing.reason}`);
59
+ console.log(` SuggestedFix : ${result.healing.suggestedFix}`);
60
+ console.log(` Confidence : ${result.healing.confidence}`);
61
+ } else {
62
+ console.log(" Not safe to auto-heal");
63
+ }
64
+
65
+ console.log("\nAI Advice:");
66
+ console.log(` Summary: ${result.llm.summary}`);
67
+ result.llm.fixRecommendation.forEach(r =>
68
+ console.log(` - ${r}`)
69
+ );
70
+
71
+ console.log("==================================================");
72
+ }
73
+
74
+ run();
@@ -0,0 +1,40 @@
1
+ import { test as base, expect } from '@playwright/test';
2
+
3
+ type FailureHint = {
4
+ type: 'API_BUG' | 'UI_BUG';
5
+ reason: string;
6
+ };
7
+
8
+ export const test = base.extend({
9
+ page: async ({ page }, use, testInfo) => {
10
+ try {
11
+ await use(page);
12
+ } catch (error: any) {
13
+ const message = error?.message ?? '';
14
+
15
+ let hint: FailureHint | null = null;
16
+
17
+ // ✅ Numeric assertion mismatch → API_BUG
18
+ if (
19
+ /Expected:\s*\d+/i.test(message) &&
20
+ /Received:\s*\d+/i.test(message)
21
+ ) {
22
+ hint = {
23
+ type: 'API_BUG',
24
+ reason: 'Numeric data mismatch inferred from UI assertion'
25
+ };
26
+ }
27
+
28
+ if (hint) {
29
+ await testInfo.attach('failure-hint', {
30
+ body: JSON.stringify(hint, null, 2),
31
+ contentType: 'application/json'
32
+ });
33
+ }
34
+
35
+ throw error;
36
+ }
37
+ }
38
+ });
39
+
40
+ export { expect };
@@ -0,0 +1,74 @@
1
+ // tests/saucedemo-login-validation.spec.ts
2
+ import { test, expect } from '@playwright/test';
3
+
4
+ const URL = 'https://www.saucedemo.com/';
5
+ const USERNAME = '#user-name';
6
+ const PASSWORD = '#password';
7
+ const LOGIN_BTN = '#login-button';
8
+ const ERROR = '[data-test="error"]';
9
+
10
+ /**
11
+ * 1️⃣ VALID LOGIN
12
+ */
13
+ test('Login | VALID | standard_user should login successfully', async ({ page }) => {
14
+ await page.goto(URL);
15
+
16
+ await page.fill(USERNAME, 'standard_user');
17
+ await page.fill(PASSWORD, 'secret_sauce');
18
+ await page.click(LOGIN_BTN);
19
+
20
+ await expect(page).toHaveURL(/inventory.html/);
21
+ });
22
+
23
+ /**
24
+ * 2️⃣ INVALID USERNAME
25
+ */
26
+ test('Login | INVALID | wrong username should fail', async ({ page }) => {
27
+ await page.goto(URL);
28
+
29
+ await page.fill(USERNAME, 'invalid_user');
30
+ await page.fill(PASSWORD, 'secret_sauce');
31
+ await page.click(LOGIN_BTN);
32
+
33
+ await expect(page.locator(ERROR)).toBeVisible();
34
+ await expect(page.locator(ERROR)).toContainText(/do not match/i);
35
+ });
36
+
37
+ /**
38
+ * 3️⃣ LOCKED OUT USER
39
+ */
40
+ test('Login | LOCKED | locked_out_user should be blocked', async ({ page }) => {
41
+ await page.goto(URL);
42
+
43
+ await page.fill(USERNAME, 'locked_out_user');
44
+ await page.fill(PASSWORD, 'secret_sauce');
45
+ await page.click(LOGIN_BTN);
46
+
47
+ await expect(page.locator(ERROR)).toBeVisible();
48
+ await expect(page.locator(ERROR)).toContainText(/locked out/i);
49
+ });
50
+
51
+ /**
52
+ * 4️⃣ EMPTY CREDENTIALS
53
+ */
54
+ test('Login | EMPTY | username and password required', async ({ page }) => {
55
+ await page.goto(URL);
56
+
57
+ await page.click(LOGIN_BTN);
58
+
59
+ await expect(page.locator(ERROR)).toBeVisible();
60
+ await expect(page.locator(ERROR)).toContainText(/Username is required/i);
61
+ });
62
+
63
+ /**
64
+ * 5️⃣ SQL-LIKE INPUT (SECURITY SANITY)
65
+ */
66
+ test('Login | SECURITY | SQL-like input should be rejected', async ({ page }) => {
67
+ await page.goto(URL);
68
+
69
+ await page.fill(USERNAME, `' OR 1=1 --`);
70
+ await page.fill(PASSWORD, `' OR 1=1 --`);
71
+ await page.click(LOGIN_BTN);
72
+
73
+ await expect(page.locator(ERROR)).toBeVisible();
74
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "dist",
4
+ "rootDir": ".",
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "target": "ES2022",
8
+ "esModuleInterop": true,
9
+ "strict": true,
10
+ "skipLibCheck": true
11
+ },
12
+ "include": [
13
+ "src/**/*",
14
+ "bin/**/*"
15
+ ]
16
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "types": ["node", "@playwright/test"],
5
+ "noImplicitAny": true,
6
+ "strict": true
7
+ },
8
+ "include": [
9
+ "tests/**/*.ts",
10
+ "tests/**/*.tsx",
11
+ "src/**/*.ts"
12
+ ]
13
+ }