qa360 2.1.7 → 2.2.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 (906) hide show
  1. package/.BETA_TESTING_FEEDBACK.md +256 -0
  2. package/.claude/settings.local.json +154 -0
  3. package/.editorconfig +21 -0
  4. package/.github/CODEOWNERS +23 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +108 -0
  6. package/.github/ISSUE_TEMPLATE/feedback_dx.yml +121 -0
  7. package/.github/dependabot.yml +35 -0
  8. package/.github/workflows/mcp-dx.yml +106 -0
  9. package/.github/workflows/release.yml +26 -0
  10. package/.github/workflows/test.yml +93 -0
  11. package/.nvmrc +1 -0
  12. package/.qa360-artifacts/.gitkeep +0 -0
  13. package/.qa360-artifacts/baselines/.gitkeep +0 -0
  14. package/.qa360-artifacts/cache/.gitkeep +0 -0
  15. package/.qa360-artifacts/reports/.gitkeep +0 -0
  16. package/.qa360-artifacts/screenshots/.gitkeep +0 -0
  17. package/.qa360-baselines/www_xyqo_ai.baseline.json +33 -0
  18. package/CHANGELOG.md +234 -0
  19. package/CODEOWNERS +43 -0
  20. package/CONTRIBUTING.md +273 -0
  21. package/NOVICE_USER_GUIDE.md +272 -0
  22. package/QUICK_START.md +191 -0
  23. package/README.md +191 -163
  24. package/adapters/README.md +46 -0
  25. package/check-branches.sh +32 -0
  26. package/cli/.qa360/keys/ed25519.key +1 -0
  27. package/cli/.qa360/keys/ed25519.pub +1 -0
  28. package/cli/CHANGELOG.md +84 -0
  29. package/cli/LICENSE +24 -0
  30. package/cli/README.md +222 -0
  31. package/cli/examples/README.md +160 -0
  32. package/cli/package.json +76 -0
  33. package/cli/scripts/bundle-for-npm.sh +51 -0
  34. package/cli/scripts/validate-package.js +116 -0
  35. package/cli/src/__tests__/commands/doctor.test.ts +108 -0
  36. package/cli/src/__tests__/index.test.ts +15 -0
  37. package/cli/src/cli-minimal.ts +44 -0
  38. package/cli/src/commands/__tests__/crawl.test.ts +412 -0
  39. package/cli/src/commands/__tests__/doctor-qa360-home.test.ts +156 -0
  40. package/cli/src/commands/__tests__/e2e-ui-tests.test.ts +494 -0
  41. package/cli/src/commands/__tests__/e2e.test.ts +187 -0
  42. package/cli/src/commands/__tests__/flakiness.test.ts +528 -0
  43. package/cli/src/commands/__tests__/generate.test.ts +507 -0
  44. package/cli/src/commands/__tests__/history.integration.test.ts +358 -0
  45. package/cli/src/commands/__tests__/history.test.ts +433 -0
  46. package/cli/src/commands/__tests__/monitor-realworld.test.ts +199 -0
  47. package/cli/src/commands/__tests__/monitor.test.ts +81 -0
  48. package/cli/src/commands/__tests__/ollama.test.ts +529 -0
  49. package/cli/src/commands/__tests__/repair.test.ts +225 -0
  50. package/cli/src/commands/__tests__/report.integration.test.ts +167 -0
  51. package/cli/src/commands/__tests__/report.test.ts +294 -0
  52. package/cli/src/commands/__tests__/report.vitest.ts +288 -0
  53. package/cli/src/commands/__tests__/retry.test.ts +78 -0
  54. package/cli/src/commands/__tests__/run.integration.test.ts +240 -0
  55. package/cli/src/commands/__tests__/run.test.ts +346 -0
  56. package/cli/src/commands/__tests__/run.vitest.ts +301 -0
  57. package/cli/src/commands/__tests__/secrets.test.ts +114 -0
  58. package/cli/src/commands/__tests__/serve.test.ts +80 -0
  59. package/cli/src/commands/__tests__/verify.test.ts +103 -0
  60. package/cli/src/commands/ai.ts +702 -0
  61. package/cli/src/commands/ask.ts +678 -0
  62. package/cli/src/commands/coverage.ts +305 -0
  63. package/cli/src/commands/crawl.ts +155 -0
  64. package/cli/src/commands/doctor.ts +610 -0
  65. package/cli/src/commands/examples.ts +248 -0
  66. package/cli/src/commands/explain.ts +710 -0
  67. package/cli/src/commands/flakiness.ts +560 -0
  68. package/cli/src/commands/generate.ts +566 -0
  69. package/cli/src/commands/history.ts +914 -0
  70. package/cli/src/commands/init.ts +777 -0
  71. package/cli/src/commands/monitor.ts +270 -0
  72. package/cli/src/commands/ollama.ts +337 -0
  73. package/cli/src/commands/pack.ts +497 -0
  74. package/cli/src/commands/regression.ts +400 -0
  75. package/cli/src/commands/repair.ts +356 -0
  76. package/cli/src/commands/report.ts +463 -0
  77. package/cli/src/commands/retry.ts +380 -0
  78. package/cli/src/commands/run.ts +218 -0
  79. package/cli/src/commands/scan.ts +177 -0
  80. package/cli/src/commands/secrets.ts +340 -0
  81. package/cli/src/commands/serve.ts +194 -0
  82. package/cli/src/commands/slo.ts +387 -0
  83. package/cli/src/commands/verify-temp-note.md +11 -0
  84. package/cli/src/commands/verify.ts +322 -0
  85. package/cli/src/generators/index.ts +6 -0
  86. package/cli/src/generators/json-reporter.ts +15 -0
  87. package/cli/src/generators/test-generator.ts +90 -0
  88. package/cli/src/index.ts +289 -0
  89. package/cli/src/scanners/dom-scanner.ts +360 -0
  90. package/cli/src/scanners/index.ts +5 -0
  91. package/cli/src/types/scan.ts +84 -0
  92. package/cli/src/utils/config.ts +145 -0
  93. package/cli/tsconfig.bundle.json +12 -0
  94. package/cli/tsconfig.json +23 -0
  95. package/cli/vitest.config.ts +59 -0
  96. package/core/LICENSE +24 -0
  97. package/core/README.md +64 -0
  98. package/core/package.json +81 -0
  99. package/core/src/__tests__/adapters-contract/adapters-contract.test.md +156 -0
  100. package/core/src/__tests__/index.test.ts +31 -0
  101. package/core/src/__tests__/integration/phase3.test.ts +405 -0
  102. package/core/src/__tests__/pack/validator.test.ts +312 -0
  103. package/core/src/__tests__/secrets/crypto.test.ts +190 -0
  104. package/core/src/__tests__/secrets/manager.test.ts +316 -0
  105. package/core/src/__tests__/security/redactor-phase3.test.ts +233 -0
  106. package/core/src/__tests__/serve/health-checker.test.ts +155 -0
  107. package/core/src/__tests__/serve/process-manager.test.ts +213 -0
  108. package/core/src/__tests__/serve/server.test.ts +103 -0
  109. package/core/src/__tests__/vault/cas.test.ts +178 -0
  110. package/core/src/__tests__/vault/vault.test.ts +296 -0
  111. package/core/src/adapters/__tests__/fixtures/jest-coverage.json +8 -0
  112. package/core/src/adapters/__tests__/fixtures/jest-results.json +41 -0
  113. package/core/src/adapters/__tests__/fixtures/pytest-junit.xml +16 -0
  114. package/core/src/adapters/__tests__/fixtures/vitest-coverage.json +8 -0
  115. package/core/src/adapters/__tests__/fixtures/vitest-results.json +50 -0
  116. package/core/src/adapters/__tests__/gitleaks-secrets.test.ts +452 -0
  117. package/core/src/adapters/__tests__/jest-adapter.test.ts +276 -0
  118. package/core/src/adapters/__tests__/k6-perf.test.ts +538 -0
  119. package/core/src/adapters/__tests__/osv-deps.test.ts +471 -0
  120. package/core/src/adapters/__tests__/playwright-native-api.test.ts +792 -0
  121. package/core/src/adapters/__tests__/playwright-ui-e2e.test.ts +431 -0
  122. package/core/src/adapters/__tests__/playwright-ui.test.ts +1073 -0
  123. package/core/src/adapters/__tests__/pytest-adapter.test.ts +207 -0
  124. package/core/src/adapters/__tests__/semgrep-sast.test.ts +436 -0
  125. package/core/src/adapters/__tests__/vitest-adapter.test.ts +208 -0
  126. package/core/src/adapters/__tests__/zap-dast.test.ts +453 -0
  127. package/core/src/adapters/gitleaks-secrets.ts +521 -0
  128. package/core/src/adapters/jest-adapter.ts +306 -0
  129. package/core/src/adapters/k6-perf.ts +479 -0
  130. package/core/src/adapters/osv-deps.ts +467 -0
  131. package/core/src/adapters/playwright-native-adapter.ts +472 -0
  132. package/core/src/adapters/playwright-native-api.ts +619 -0
  133. package/core/src/adapters/playwright-ui.ts +1088 -0
  134. package/core/src/adapters/pytest-adapter.ts +472 -0
  135. package/core/src/adapters/semgrep-sast.ts +410 -0
  136. package/core/src/adapters/unit-test-types.ts +106 -0
  137. package/core/src/adapters/vitest-adapter.ts +295 -0
  138. package/core/src/adapters/zap-dast.ts +551 -0
  139. package/core/src/ai/__tests__/deepseek-provider.test.ts +586 -0
  140. package/core/src/ai/__tests__/ollama-provider.test.ts +641 -0
  141. package/core/src/ai/anthropic-provider.ts +262 -0
  142. package/core/src/ai/deepseek-provider.ts +315 -0
  143. package/core/src/ai/index.ts +87 -0
  144. package/core/src/ai/llm-client.ts +52 -0
  145. package/core/src/ai/mock-provider.ts +146 -0
  146. package/core/src/ai/ollama-provider.ts +269 -0
  147. package/core/src/ai/openai-provider.ts +240 -0
  148. package/core/src/ai/provider-factory.ts +408 -0
  149. package/core/src/artifacts/README.md +78 -0
  150. package/core/src/artifacts/index.ts +16 -0
  151. package/core/src/artifacts/ui-artifacts.ts +412 -0
  152. package/core/src/assertions/__tests__/engine.test.ts +360 -0
  153. package/core/src/assertions/engine.ts +577 -0
  154. package/core/src/assertions/index.ts +13 -0
  155. package/core/src/assertions/types.ts +229 -0
  156. package/core/src/auth/__tests__/api-key-provider.test.ts +282 -0
  157. package/core/src/auth/__tests__/auth-manager.test.ts +430 -0
  158. package/core/src/auth/__tests__/basic-auth-provider.test.ts +364 -0
  159. package/core/src/auth/__tests__/cloud-providers.test.ts +751 -0
  160. package/core/src/auth/__tests__/jwt-provider.test.ts +400 -0
  161. package/core/src/auth/__tests__/oauth2-provider.test.ts +383 -0
  162. package/core/src/auth/__tests__/totp-provider.test.ts +294 -0
  163. package/core/src/auth/__tests__/ui-login-provider.test.ts +323 -0
  164. package/core/src/auth/api-key-provider.ts +75 -0
  165. package/core/src/auth/aws-iam-provider.ts +212 -0
  166. package/core/src/auth/azure-ad-provider.ts +126 -0
  167. package/core/src/auth/basic-auth-provider.ts +133 -0
  168. package/core/src/auth/gcp-adc-provider.ts +146 -0
  169. package/core/src/auth/index.ts +342 -0
  170. package/core/src/auth/jwt-provider.ts +193 -0
  171. package/core/src/auth/manager.ts +281 -0
  172. package/core/src/auth/oauth2-provider.ts +141 -0
  173. package/core/src/auth/totp-provider.ts +163 -0
  174. package/core/src/auth/ui-login-provider.ts +242 -0
  175. package/core/src/cache/__tests__/lru-cache.test.ts +564 -0
  176. package/core/src/cache/index.ts +13 -0
  177. package/core/src/cache/lru-cache.ts +536 -0
  178. package/core/src/crawler/__tests__/journey-generator.test.ts +344 -0
  179. package/core/src/crawler/__tests__/selector-generator.test.ts +211 -0
  180. package/core/src/crawler/index.ts +335 -0
  181. package/core/src/crawler/journey-generator.ts +471 -0
  182. package/core/src/crawler/page-analyzer.ts +857 -0
  183. package/core/src/crawler/selector-generator.ts +280 -0
  184. package/core/src/crawler/types.ts +475 -0
  185. package/core/src/dashboard/__tests__/real-world.test.ts +430 -0
  186. package/core/src/dashboard/__tests__/server.test.ts +283 -0
  187. package/core/src/dashboard/__tests__/types.test.ts +208 -0
  188. package/core/src/dashboard/assets.ts +692 -0
  189. package/core/src/dashboard/index.ts +17 -0
  190. package/core/src/dashboard/server.ts +401 -0
  191. package/core/src/dashboard/types.ts +78 -0
  192. package/core/src/discoverer/__tests__/test-discoverer.test.ts +444 -0
  193. package/core/src/discoverer/index.ts +374 -0
  194. package/core/src/fixtures/__tests__/loader.test.ts +246 -0
  195. package/core/src/fixtures/__tests__/resolver.test.ts +334 -0
  196. package/core/src/fixtures/index.ts +9 -0
  197. package/core/src/fixtures/loader.ts +189 -0
  198. package/core/src/fixtures/resolver.ts +221 -0
  199. package/core/src/fixtures/types.ts +86 -0
  200. package/core/src/flakiness/__tests__/flakiness.test.ts +554 -0
  201. package/core/src/flakiness/index.ts +536 -0
  202. package/core/src/generation/__tests__/code-formatter.test.ts +170 -0
  203. package/core/src/generation/__tests__/code-generator-contract.test.ts +207 -0
  204. package/core/src/generation/__tests__/code-generator.test.ts +586 -0
  205. package/core/src/generation/__tests__/crawler-pack-generator.test.ts +479 -0
  206. package/core/src/generation/__tests__/generation-e2e-b2bshop.test.ts +718 -0
  207. package/core/src/generation/__tests__/generation-integration.test.ts +655 -0
  208. package/core/src/generation/__tests__/pack-generator.test.ts +408 -0
  209. package/core/src/generation/__tests__/prompt-builder.test.ts +200 -0
  210. package/core/src/generation/__tests__/real-provider-integration.test.ts +414 -0
  211. package/core/src/generation/__tests__/source-analyzer.test.ts +774 -0
  212. package/core/src/generation/__tests__/test-optimizer.test.ts +255 -0
  213. package/core/src/generation/code-formatter.ts +408 -0
  214. package/core/src/generation/code-generator.ts +470 -0
  215. package/core/src/generation/crawler-pack-generator.ts +289 -0
  216. package/core/src/generation/generator.ts +113 -0
  217. package/core/src/generation/index.ts +59 -0
  218. package/core/src/generation/pack-generator.ts +527 -0
  219. package/core/src/generation/prompt-builder.ts +772 -0
  220. package/core/src/generation/source-analyzer.ts +830 -0
  221. package/core/src/generation/test-optimizer.ts +474 -0
  222. package/core/src/generation/types.ts +217 -0
  223. package/core/src/hooks/__tests__/compose.test.ts +636 -0
  224. package/core/src/hooks/__tests__/runner.test.ts +478 -0
  225. package/core/src/hooks/compose.ts +268 -0
  226. package/core/src/hooks/runner.ts +364 -0
  227. package/core/src/index.ts +255 -0
  228. package/core/src/pack/__tests__/migrator.test.ts +594 -0
  229. package/core/src/pack/__tests__/validator.test.ts +759 -0
  230. package/core/src/pack/migrator.ts +353 -0
  231. package/core/src/pack/validator.ts +359 -0
  232. package/core/src/pack-v2/__tests__/loader.test.ts +533 -0
  233. package/core/src/pack-v2/__tests__/migrator.test.ts +455 -0
  234. package/core/src/pack-v2/__tests__/validator.test.ts +609 -0
  235. package/core/src/pack-v2/index.ts +41 -0
  236. package/core/src/pack-v2/loader.ts +358 -0
  237. package/core/src/pack-v2/migrator.ts +540 -0
  238. package/core/src/pack-v2/validator.ts +726 -0
  239. package/core/src/parallel/README.md +143 -0
  240. package/core/src/parallel/index.ts +16 -0
  241. package/core/src/parallel/parallel-runner.ts +282 -0
  242. package/core/src/pom/__tests__/loader.test.ts +378 -0
  243. package/core/src/pom/base-page.ts +425 -0
  244. package/core/src/pom/index.ts +45 -0
  245. package/core/src/pom/loader.ts +480 -0
  246. package/core/src/pom/types.ts +146 -0
  247. package/core/src/proof/__tests__/proof-roundtrip.test.ts +149 -0
  248. package/core/src/proof/__tests__/schema-validation-manual.mjs +211 -0
  249. package/core/src/proof/__tests__/schema-validation.test.ts +336 -0
  250. package/core/src/proof/__tests__/signer.test.ts +486 -0
  251. package/core/src/proof/__tests__/temporal-regression.test.ts +537 -0
  252. package/core/src/proof/__tests__/verifier-advanced.test.ts +588 -0
  253. package/core/src/proof/__tests__/verifier.test.ts +413 -0
  254. package/core/src/proof/bundle.ts +290 -0
  255. package/core/src/proof/canonicalize.ts +116 -0
  256. package/core/src/proof/index.ts +74 -0
  257. package/core/src/proof/schema.ts +285 -0
  258. package/core/src/proof/signer.ts +293 -0
  259. package/core/src/proof/verifier.ts +380 -0
  260. package/core/src/regression/__tests__/detector.test.ts +396 -0
  261. package/core/src/regression/__tests__/trend-analyzer.test.ts +300 -0
  262. package/core/src/regression/detector.ts +629 -0
  263. package/core/src/regression/index.ts +34 -0
  264. package/core/src/regression/trend-analyzer.ts +468 -0
  265. package/core/src/regression/types.ts +295 -0
  266. package/core/src/regression/vault.ts +419 -0
  267. package/core/src/repair/__tests__/repairer.test.ts +572 -0
  268. package/core/src/repair/__tests__/types.test.ts +302 -0
  269. package/core/src/repair/engine/__tests__/fixer.test.ts +482 -0
  270. package/core/src/repair/engine/__tests__/suggestion-engine.test.ts +395 -0
  271. package/core/src/repair/engine/fixer.ts +271 -0
  272. package/core/src/repair/engine/suggestion-engine.ts +234 -0
  273. package/core/src/repair/index.ts +53 -0
  274. package/core/src/repair/repairer.ts +376 -0
  275. package/core/src/repair/types.ts +119 -0
  276. package/core/src/repair/utils/__tests__/error-analyzer.test.ts +454 -0
  277. package/core/src/repair/utils/error-analyzer.ts +308 -0
  278. package/core/src/reporting/README.md +144 -0
  279. package/core/src/reporting/html-reporter.ts +835 -0
  280. package/core/src/reporting/index.ts +16 -0
  281. package/core/src/retry/README.md +192 -0
  282. package/core/src/retry/__tests__/flakiness-integration.test.ts +475 -0
  283. package/core/src/retry/__tests__/retry-engine.test.ts +424 -0
  284. package/core/src/retry/flakiness-integration.ts +267 -0
  285. package/core/src/retry/index.ts +48 -0
  286. package/core/src/retry/retry-engine.ts +368 -0
  287. package/core/src/retry/types.ts +208 -0
  288. package/core/src/retry/vault.ts +413 -0
  289. package/core/src/runner/__tests__/flakiness-integration.test.ts +566 -0
  290. package/core/src/runner/__tests__/phase3-e2e-b2bshop.test.ts +218 -0
  291. package/core/src/runner/__tests__/phase3-e2e-reqres.test.ts +199 -0
  292. package/core/src/runner/__tests__/phase3-runner.test.ts +1118 -0
  293. package/core/src/runner/e2e-helpers.ts +216 -0
  294. package/core/src/runner/phase3-runner.ts +1236 -0
  295. package/core/src/schemas/gherkin-report.json +122 -0
  296. package/core/src/secrets/__tests__/crypto.test.ts +180 -0
  297. package/core/src/secrets/crypto.ts +289 -0
  298. package/core/src/secrets/manager.ts +272 -0
  299. package/core/src/security/__tests__/hardening.test.ts +480 -0
  300. package/core/src/security/redaction-patterns-extended.ts +278 -0
  301. package/core/src/security/redactor.ts +326 -0
  302. package/core/src/self-healing/assertion-healer.ts +485 -0
  303. package/core/src/self-healing/engine.ts +626 -0
  304. package/core/src/self-healing/index.ts +33 -0
  305. package/core/src/self-healing/selector-healer.ts +488 -0
  306. package/core/src/self-healing/types.ts +193 -0
  307. package/core/src/serve/diagnostics-collector.ts +201 -0
  308. package/core/src/serve/health-checker.ts +274 -0
  309. package/core/src/serve/index.ts +9 -0
  310. package/core/src/serve/metrics-collector.ts +386 -0
  311. package/core/src/serve/process-manager.ts +265 -0
  312. package/core/src/serve/server.ts +230 -0
  313. package/core/src/slo/config.ts +408 -0
  314. package/core/src/slo/index.ts +68 -0
  315. package/core/src/slo/sli-calculator.ts +474 -0
  316. package/core/src/slo/slo-tracker.ts +481 -0
  317. package/core/src/slo/types.ts +408 -0
  318. package/core/src/slo/vault.ts +600 -0
  319. package/core/src/tui/__tests__/monitor.test.ts +336 -0
  320. package/core/src/tui/__tests__/real-world.test.ts +376 -0
  321. package/core/src/tui/__tests__/renderer.test.ts +201 -0
  322. package/core/src/tui/__tests__/types.test.ts +295 -0
  323. package/core/src/tui/index.ts +19 -0
  324. package/core/src/tui/monitor.ts +331 -0
  325. package/core/src/tui/renderer.ts +269 -0
  326. package/core/src/tui/types.ts +68 -0
  327. package/core/src/types/pack-v1.ts +305 -0
  328. package/core/src/types/pack-v2.ts +501 -0
  329. package/core/src/types/trust-score.ts +258 -0
  330. package/core/src/vault/__tests__/flakiness-vault.test.ts +562 -0
  331. package/core/src/vault/__tests__/vault.test.ts +259 -0
  332. package/core/src/vault/cas.ts +323 -0
  333. package/core/src/vault/index.ts +1361 -0
  334. package/core/src/vault/schema.sql +168 -0
  335. package/core/src/visual/README.md +185 -0
  336. package/core/src/visual/index.ts +14 -0
  337. package/core/src/visual/visual-regression.ts +347 -0
  338. package/core/src/watch/__tests__/watch-mode.test.ts +192 -0
  339. package/core/src/watch/index.ts +14 -0
  340. package/core/src/watch/watch-mode.ts +565 -0
  341. package/core/tsconfig.json +12 -0
  342. package/core/vitest.config.ts +52 -0
  343. package/docs/ARCHITECTURE.md +901 -0
  344. package/docs/AUDIT-GLOBAL-DEC2025.md +271 -0
  345. package/docs/BETA_TESTING.md +257 -0
  346. package/docs/BETA_TESTING_PLAN.md +727 -0
  347. package/docs/CERTIFICATION-REPORT.md +142 -0
  348. package/docs/COMPLETE_AUDIT_REFACTORING.md +965 -0
  349. package/docs/DEVELOPMENT.md +545 -0
  350. package/docs/DEVELOPMENT_HISTORY.md +345 -0
  351. package/docs/LIMITATIONS.md +176 -0
  352. package/docs/MIGRATION.md +303 -0
  353. package/docs/OPTION_3_4_EXPLORATION.md +1257 -0
  354. package/docs/PHASE1_PERFORMANCE.md +144 -0
  355. package/docs/QA360_Cloud.postman_collection.json +89 -0
  356. package/docs/QA360_TESTING_PHILOSOPHY.md +769 -0
  357. package/docs/QA_TEST_PLAN.md +727 -0
  358. package/docs/README.md +50 -0
  359. package/docs/STATUS.md +198 -0
  360. package/docs/STRATEGIC_STUDY_GOOSE_INTEGRATION.md +615 -0
  361. package/docs/USER_GUIDE.md +687 -0
  362. package/docs/WORK-DONE-ADAPTER-TESTS.md +136 -0
  363. package/docs/adapters-security.md +485 -0
  364. package/docs/architecture-diagram.mmd +168 -0
  365. package/docs/archive/ARCH-01-DAY6-BUILD-FIXES.md +396 -0
  366. package/docs/archive/ARCH-01-DAY6-FINAL-STATUS.md +324 -0
  367. package/docs/archive/ARCH-01_MCP_MERGE_ANALYSIS.md +644 -0
  368. package/docs/archive/ARCH-01_NEXT_STEPS.md +60 -0
  369. package/docs/archive/BRANCH_PROTECTION.md +183 -0
  370. package/docs/archive/CI_LOCKDOWN_CHECKLIST.md +222 -0
  371. package/docs/archive/HANDOFF_TEST-01.md +669 -0
  372. package/docs/archive/LEGAL_READY_PLACEHOLDERS.md +372 -0
  373. package/docs/archive/NODE_UPGRADE_GUIDE.md +188 -0
  374. package/docs/archive/PHASE1_COMPLETION.md +386 -0
  375. package/docs/archive/PHASE2_COMPLETION.md +404 -0
  376. package/docs/archive/PHASE3_AND_4_FINAL.md +360 -0
  377. package/docs/archive/PHASE3_COMPLETE.md +301 -0
  378. package/docs/archive/PHASE3_STATUS.md +255 -0
  379. package/docs/archive/PRE-WEEK2-AUDIT.md +364 -0
  380. package/docs/archive/README.md +16 -0
  381. package/docs/archive/SCHEMA_AJV_2020_FIX.md +245 -0
  382. package/docs/archive/TEST-01_AUDIT_REPORT.md +240 -0
  383. package/docs/archive/TEST-01_COVERAGE_PLAN.md +423 -0
  384. package/docs/archive/obsolete-proposals/dom-element-discovery-mode.md +250 -0
  385. package/docs/archive/obsolete-proposals/qa360-comprehensive-test-plan.md +1249 -0
  386. package/docs/archive/obsolete-proposals/qa360-quick-start-guide.md +298 -0
  387. package/docs/archive/obsolete-proposals/technical-plan-dom-discovery.md +870 -0
  388. package/docs/budgets-advanced.md +308 -0
  389. package/docs/examples/history-export-gc.md +285 -0
  390. package/docs/examples/pack-v2-complete.yaml +158 -0
  391. package/docs/examples/pack-v2-quickstart.yaml +24 -0
  392. package/docs/examples/pack-v2-ui-login.yaml +81 -0
  393. package/docs/examples/qa360-report.json +50 -0
  394. package/docs/history.md +565 -0
  395. package/docs/hooks.md +304 -0
  396. package/docs/llm-providers.md +512 -0
  397. package/docs/mcp-server.md +651 -0
  398. package/docs/mcp-tools.md +1131 -0
  399. package/docs/pack-v1.md +383 -0
  400. package/docs/pack-v2.md +558 -0
  401. package/docs/page-objects.md +366 -0
  402. package/docs/proofs.md +670 -0
  403. package/docs/quickstart-5min.md +257 -0
  404. package/docs/readiness-ci.md +654 -0
  405. package/docs/rfc/README.md +20 -0
  406. package/docs/rfc/proof-bundle-v1.md +787 -0
  407. package/docs/secrets.md +392 -0
  408. package/docs/serve.md +494 -0
  409. package/docs/unit-test-adapters.md +168 -0
  410. package/docs/vault.md +491 -0
  411. package/e2e/qa360-e2e.test.ts +696 -0
  412. package/e2e/vitest.config.ts +18 -0
  413. package/examples/README.md +30 -140
  414. package/examples/ci/docker-compose-serve.yml +375 -0
  415. package/examples/ci/github-actions-serve.yml +345 -0
  416. package/examples/ci/gitlab-ci-serve.yml +407 -0
  417. package/examples/datasets/README.md +101 -0
  418. package/examples/datasets/b2bshop.ts +155 -0
  419. package/examples/datasets/index.ts +57 -0
  420. package/examples/datasets/reqres.ts +195 -0
  421. package/examples/fixtures-demo/fixtures/users.yml +39 -0
  422. package/examples/fixtures-demo/pack.yml +71 -0
  423. package/examples/future-api/README.md +16 -0
  424. package/examples/future-api/diag.js +7 -0
  425. package/examples/future-api/health.js +4 -0
  426. package/examples/future-api/packs.js +13 -0
  427. package/examples/future-api/runpack.js +10 -0
  428. package/examples/generation/README.md +148 -0
  429. package/examples/generation/pack-generator-example.js +115 -0
  430. package/examples/generation/source-analyzer-example.js +115 -0
  431. package/examples/httpbin/pack.yml +59 -0
  432. package/examples/load-testing/mcp-load.yml +115 -0
  433. package/examples/load-testing/mcp-stdio.yml +95 -0
  434. package/examples/mcp/claude-desktop-config.json +33 -0
  435. package/examples/mcp/claude-desktop.json +16 -0
  436. package/examples/mcp/conversation-sample.md +131 -0
  437. package/examples/mcp/demo-60s.md +330 -0
  438. package/examples/mcp/sample-conversation.jsonl +21 -0
  439. package/examples/mcp/vscode-settings.json +22 -0
  440. package/examples/pack-v2-complete.yml +242 -0
  441. package/examples/pack-v2-examples.md +244 -0
  442. package/examples/pack-v2-quickstart.yml +55 -0
  443. package/examples/packs-business/ecommerce-api.yml +121 -0
  444. package/examples/packs-business/saas-dashboard-ui.yml +133 -0
  445. package/examples/packs-conformance/compose-multi.yml +174 -0
  446. package/examples/packs-conformance/full.yml +152 -0
  447. package/examples/packs-conformance/heavy-artifacts.yml +152 -0
  448. package/examples/packs-conformance/minimal.yml +71 -0
  449. package/examples/packs-conformance/secrets-missing.yml +97 -0
  450. package/examples/packs-conformance/timeouts.yml +77 -0
  451. package/examples/pom-demo/README.md +104 -0
  452. package/examples/pom-demo/pack.yml +60 -0
  453. package/examples/pom-demo/pages/DashboardPage.page.ts +73 -0
  454. package/examples/pom-demo/pages/LoginPage.page.ts +76 -0
  455. package/examples/proofs/e2e-playwright-proof.json +75 -0
  456. package/examples/proofs/httpbin-proof.json +69 -0
  457. package/examples/proofs/multi-adapter-proof.json +117 -0
  458. package/examples/proofs/test-proof.json +26 -0
  459. package/examples/restful-api-dev/README.md +102 -0
  460. package/examples/restful-api-dev/restful-api-advanced.yml +29 -0
  461. package/examples/restful-api-dev/restful-api-basic.yml +29 -0
  462. package/examples/web-lite/.github/workflows/qa360-phase3.yml +73 -0
  463. package/examples/web-lite/api-mock/server.js +258 -0
  464. package/examples/web-lite/pack.yml +71 -0
  465. package/examples/web-lite/services.yml +43 -0
  466. package/examples/web-lite/web-content/healthz +1 -0
  467. package/examples/web-lite/web-content/index.html +259 -0
  468. package/package.json +55 -45
  469. package/packages/mcp/CHANGELOG.md +109 -0
  470. package/packages/mcp/IMPLEMENTATION_SUMMARY.md +350 -0
  471. package/packages/mcp/LICENSE +21 -0
  472. package/packages/mcp/QUICK_START.md +291 -0
  473. package/packages/mcp/README.md +294 -0
  474. package/packages/mcp/TELEMETRY.md +220 -0
  475. package/packages/mcp/package.json +91 -0
  476. package/packages/mcp/scripts/generate-sbom-fallback.cjs +84 -0
  477. package/packages/mcp/scripts/safe-postinstall.cjs +32 -0
  478. package/packages/mcp/src/__tests__/contract.test.ts +902 -0
  479. package/packages/mcp/src/cli/cli.ts +137 -0
  480. package/packages/mcp/src/cli/doctor.ts +286 -0
  481. package/packages/mcp/src/cli/fix.ts +99 -0
  482. package/packages/mcp/src/cli/init.ts +233 -0
  483. package/packages/mcp/src/cli/postinstall.ts +14 -0
  484. package/packages/mcp/src/cli/reset.ts +44 -0
  485. package/packages/mcp/src/cli/telemetry.ts +166 -0
  486. package/packages/mcp/src/cli/test-dx.ts +94 -0
  487. package/packages/mcp/src/cli/uninstall.ts +80 -0
  488. package/packages/mcp/src/cli/up.ts +178 -0
  489. package/packages/mcp/src/index.ts +12 -0
  490. package/packages/mcp/src/scripts/e2e-local.ts +337 -0
  491. package/packages/mcp/src/scripts/verify-settings.ts +242 -0
  492. package/packages/mcp/src/security/audit.ts +244 -0
  493. package/packages/mcp/src/security/manager.ts +242 -0
  494. package/packages/mcp/src/server/full-server.ts +212 -0
  495. package/packages/mcp/src/server/minimal-server.ts +134 -0
  496. package/packages/mcp/src/tools/history.ts +388 -0
  497. package/packages/mcp/src/tools/pack.ts +449 -0
  498. package/packages/mcp/src/tools/registry.ts +638 -0
  499. package/packages/mcp/src/tools/report.ts +100 -0
  500. package/packages/mcp/src/tools/run.ts +268 -0
  501. package/packages/mcp/src/tools/secrets.ts +198 -0
  502. package/packages/mcp/src/tools/serve.ts +221 -0
  503. package/packages/mcp/src/tools/triage.ts +532 -0
  504. package/packages/mcp/src/tools/types.ts +26 -0
  505. package/packages/mcp/src/tools/vault.ts +164 -0
  506. package/packages/mcp/src/tools/verify.ts +166 -0
  507. package/packages/mcp/src/types/index.ts +311 -0
  508. package/packages/mcp/src/types/mcp-stubs.ts +83 -0
  509. package/packages/mcp/tsconfig.json +16 -0
  510. package/playwright.config.ts +20 -0
  511. package/pnpm-workspace.yaml +4 -0
  512. package/run-test-and-push.sh +20 -0
  513. package/scripts/build-proof-cli.sh +110 -0
  514. package/scripts/ci/check-windows-paths.js +92 -0
  515. package/scripts/ci/invariants.sh +124 -0
  516. package/scripts/ci/make-final-bundle.js +106 -0
  517. package/scripts/ci/mcp-run-multipack.js +305 -0
  518. package/scripts/ci/run-pack-suite.sh +103 -0
  519. package/scripts/ci/run-phase7-final.sh +190 -0
  520. package/scripts/ci/slo-assert.js +158 -0
  521. package/scripts/ci/test-fault-tolerance.sh +301 -0
  522. package/scripts/install-mcp.sh +66 -0
  523. package/scripts/mcp-smoke.mjs +27 -0
  524. package/scripts/smoke.sh +26 -0
  525. package/scripts/stress-test.js +288 -0
  526. package/scripts/sync-version.mjs +50 -0
  527. package/scripts/validate-examples.mjs +404 -0
  528. package/scripts/validation/simple-pack-check.sh +51 -0
  529. package/scripts/validation/validate-universal-pack.mjs +77 -0
  530. package/scripts/verify-persistence.js +127 -0
  531. package/test-pack.yaml +43 -0
  532. package/test-results/.last-run.json +4 -0
  533. package/test-runner.mjs +87 -0
  534. package/tests/artifacts.spec.js +147 -0
  535. package/tests/contracts.spec.js +239 -0
  536. package/tests/e2e/assertions.test.mjs +370 -0
  537. package/tests/e2e/crawler.test.mjs +451 -0
  538. package/tests/e2e/playwright-plus-plus.test.mjs +604 -0
  539. package/tests/e2e/proof-bundle.test.mjs +258 -0
  540. package/tests/e2e/real-world/saucedemo.test.mjs +714 -0
  541. package/tests/e2e/real-world/the-internet-herokuapp.test.mjs +760 -0
  542. package/tests/e2e/ui-actions.test.mjs +546 -0
  543. package/tests/gherkin.e2e.spec.ts +310 -0
  544. package/tests/no-console-errors.spec.js +136 -0
  545. package/tests/pdf.spec.ts +252 -0
  546. package/tests/run-pack.spec.ts +58 -0
  547. package/tsconfig.base.json +15 -0
  548. package/tsconfig.build.json +8 -0
  549. package/tsconfig.json +37 -0
  550. package/tsconfig.test.json +18 -0
  551. package/typedoc.json +37 -0
  552. package/ui/README.md +50 -0
  553. package/verify-proof.mjs +60 -0
  554. package/dist/cli-minimal.d.ts +0 -6
  555. package/dist/cli-minimal.js +0 -36
  556. package/dist/commands/ai.d.ts +0 -43
  557. package/dist/commands/ai.js +0 -616
  558. package/dist/commands/ask.d.ts +0 -94
  559. package/dist/commands/ask.js +0 -582
  560. package/dist/commands/coverage.d.ts +0 -8
  561. package/dist/commands/coverage.js +0 -252
  562. package/dist/commands/crawl.d.ts +0 -24
  563. package/dist/commands/crawl.js +0 -121
  564. package/dist/commands/doctor.d.ts +0 -54
  565. package/dist/commands/doctor.js +0 -513
  566. package/dist/commands/examples.d.ts +0 -33
  567. package/dist/commands/examples.js +0 -193
  568. package/dist/commands/explain.d.ts +0 -27
  569. package/dist/commands/explain.js +0 -630
  570. package/dist/commands/flakiness.d.ts +0 -73
  571. package/dist/commands/flakiness.js +0 -435
  572. package/dist/commands/generate.d.ts +0 -66
  573. package/dist/commands/generate.js +0 -438
  574. package/dist/commands/history.d.ts +0 -76
  575. package/dist/commands/history.js +0 -755
  576. package/dist/commands/init.d.ts +0 -106
  577. package/dist/commands/init.js +0 -616
  578. package/dist/commands/monitor.d.ts +0 -27
  579. package/dist/commands/monitor.js +0 -225
  580. package/dist/commands/ollama.d.ts +0 -40
  581. package/dist/commands/ollama.js +0 -301
  582. package/dist/commands/pack.d.ts +0 -70
  583. package/dist/commands/pack.js +0 -413
  584. package/dist/commands/regression.d.ts +0 -8
  585. package/dist/commands/regression.js +0 -340
  586. package/dist/commands/repair.d.ts +0 -26
  587. package/dist/commands/repair.js +0 -307
  588. package/dist/commands/report.d.ts +0 -62
  589. package/dist/commands/report.js +0 -378
  590. package/dist/commands/retry.d.ts +0 -43
  591. package/dist/commands/retry.js +0 -275
  592. package/dist/commands/run.d.ts +0 -41
  593. package/dist/commands/run.js +0 -169
  594. package/dist/commands/scan.d.ts +0 -5
  595. package/dist/commands/scan.js +0 -155
  596. package/dist/commands/secrets.d.ts +0 -58
  597. package/dist/commands/secrets.js +0 -289
  598. package/dist/commands/serve.d.ts +0 -13
  599. package/dist/commands/serve.js +0 -156
  600. package/dist/commands/slo.d.ts +0 -8
  601. package/dist/commands/slo.js +0 -327
  602. package/dist/commands/verify.d.ts +0 -32
  603. package/dist/commands/verify.js +0 -278
  604. package/dist/core/adapters/gitleaks-secrets.d.ts +0 -114
  605. package/dist/core/adapters/gitleaks-secrets.js +0 -410
  606. package/dist/core/adapters/k6-perf.d.ts +0 -85
  607. package/dist/core/adapters/k6-perf.js +0 -398
  608. package/dist/core/adapters/osv-deps.d.ts +0 -123
  609. package/dist/core/adapters/osv-deps.js +0 -372
  610. package/dist/core/adapters/playwright-native-adapter.d.ts +0 -121
  611. package/dist/core/adapters/playwright-native-adapter.js +0 -339
  612. package/dist/core/adapters/playwright-native-api.d.ts +0 -183
  613. package/dist/core/adapters/playwright-native-api.js +0 -465
  614. package/dist/core/adapters/playwright-ui.d.ts +0 -197
  615. package/dist/core/adapters/playwright-ui.js +0 -840
  616. package/dist/core/adapters/semgrep-sast.d.ts +0 -99
  617. package/dist/core/adapters/semgrep-sast.js +0 -322
  618. package/dist/core/adapters/zap-dast.d.ts +0 -133
  619. package/dist/core/adapters/zap-dast.js +0 -424
  620. package/dist/core/ai/anthropic-provider.d.ts +0 -50
  621. package/dist/core/ai/anthropic-provider.js +0 -223
  622. package/dist/core/ai/deepseek-provider.d.ts +0 -81
  623. package/dist/core/ai/deepseek-provider.js +0 -266
  624. package/dist/core/ai/index.d.ts +0 -60
  625. package/dist/core/ai/index.js +0 -18
  626. package/dist/core/ai/llm-client.d.ts +0 -45
  627. package/dist/core/ai/llm-client.js +0 -7
  628. package/dist/core/ai/mock-provider.d.ts +0 -49
  629. package/dist/core/ai/mock-provider.js +0 -121
  630. package/dist/core/ai/ollama-provider.d.ts +0 -78
  631. package/dist/core/ai/ollama-provider.js +0 -204
  632. package/dist/core/ai/openai-provider.d.ts +0 -48
  633. package/dist/core/ai/openai-provider.js +0 -200
  634. package/dist/core/ai/provider-factory.d.ts +0 -160
  635. package/dist/core/ai/provider-factory.js +0 -269
  636. package/dist/core/artifacts/index.d.ts +0 -6
  637. package/dist/core/artifacts/index.js +0 -6
  638. package/dist/core/artifacts/ui-artifacts.d.ts +0 -133
  639. package/dist/core/artifacts/ui-artifacts.js +0 -304
  640. package/dist/core/assertions/engine.d.ts +0 -51
  641. package/dist/core/assertions/engine.js +0 -530
  642. package/dist/core/assertions/index.d.ts +0 -11
  643. package/dist/core/assertions/index.js +0 -11
  644. package/dist/core/assertions/types.d.ts +0 -121
  645. package/dist/core/assertions/types.js +0 -37
  646. package/dist/core/auth/api-key-provider.d.ts +0 -16
  647. package/dist/core/auth/api-key-provider.js +0 -63
  648. package/dist/core/auth/aws-iam-provider.d.ts +0 -35
  649. package/dist/core/auth/aws-iam-provider.js +0 -177
  650. package/dist/core/auth/azure-ad-provider.d.ts +0 -15
  651. package/dist/core/auth/azure-ad-provider.js +0 -99
  652. package/dist/core/auth/basic-auth-provider.d.ts +0 -26
  653. package/dist/core/auth/basic-auth-provider.js +0 -111
  654. package/dist/core/auth/gcp-adc-provider.d.ts +0 -27
  655. package/dist/core/auth/gcp-adc-provider.js +0 -126
  656. package/dist/core/auth/index.d.ts +0 -238
  657. package/dist/core/auth/index.js +0 -82
  658. package/dist/core/auth/jwt-provider.d.ts +0 -19
  659. package/dist/core/auth/jwt-provider.js +0 -160
  660. package/dist/core/auth/manager.d.ts +0 -84
  661. package/dist/core/auth/manager.js +0 -230
  662. package/dist/core/auth/oauth2-provider.d.ts +0 -17
  663. package/dist/core/auth/oauth2-provider.js +0 -114
  664. package/dist/core/auth/totp-provider.d.ts +0 -31
  665. package/dist/core/auth/totp-provider.js +0 -134
  666. package/dist/core/auth/ui-login-provider.d.ts +0 -26
  667. package/dist/core/auth/ui-login-provider.js +0 -198
  668. package/dist/core/cache/index.d.ts +0 -7
  669. package/dist/core/cache/index.js +0 -6
  670. package/dist/core/cache/lru-cache.d.ts +0 -203
  671. package/dist/core/cache/lru-cache.js +0 -397
  672. package/dist/core/core/coverage/analyzer.d.ts +0 -101
  673. package/dist/core/core/coverage/analyzer.js +0 -415
  674. package/dist/core/core/coverage/collector.d.ts +0 -74
  675. package/dist/core/core/coverage/collector.js +0 -459
  676. package/dist/core/core/coverage/config.d.ts +0 -37
  677. package/dist/core/core/coverage/config.js +0 -156
  678. package/dist/core/core/coverage/index.d.ts +0 -11
  679. package/dist/core/core/coverage/index.js +0 -15
  680. package/dist/core/core/coverage/types.d.ts +0 -267
  681. package/dist/core/core/coverage/types.js +0 -6
  682. package/dist/core/core/coverage/vault.d.ts +0 -95
  683. package/dist/core/core/coverage/vault.js +0 -405
  684. package/dist/core/coverage/analyzer.d.ts +0 -101
  685. package/dist/core/coverage/analyzer.js +0 -415
  686. package/dist/core/coverage/collector.d.ts +0 -74
  687. package/dist/core/coverage/collector.js +0 -459
  688. package/dist/core/coverage/config.d.ts +0 -37
  689. package/dist/core/coverage/config.js +0 -156
  690. package/dist/core/coverage/index.d.ts +0 -11
  691. package/dist/core/coverage/index.js +0 -15
  692. package/dist/core/coverage/types.d.ts +0 -267
  693. package/dist/core/coverage/types.js +0 -6
  694. package/dist/core/coverage/vault.d.ts +0 -95
  695. package/dist/core/coverage/vault.js +0 -405
  696. package/dist/core/crawler/index.d.ts +0 -57
  697. package/dist/core/crawler/index.js +0 -281
  698. package/dist/core/crawler/journey-generator.d.ts +0 -49
  699. package/dist/core/crawler/journey-generator.js +0 -412
  700. package/dist/core/crawler/page-analyzer.d.ts +0 -88
  701. package/dist/core/crawler/page-analyzer.js +0 -709
  702. package/dist/core/crawler/selector-generator.d.ts +0 -34
  703. package/dist/core/crawler/selector-generator.js +0 -240
  704. package/dist/core/crawler/types.d.ts +0 -353
  705. package/dist/core/crawler/types.js +0 -6
  706. package/dist/core/dashboard/assets.d.ts +0 -6
  707. package/dist/core/dashboard/assets.js +0 -690
  708. package/dist/core/dashboard/index.d.ts +0 -6
  709. package/dist/core/dashboard/index.js +0 -5
  710. package/dist/core/dashboard/server.d.ts +0 -72
  711. package/dist/core/dashboard/server.js +0 -354
  712. package/dist/core/dashboard/types.d.ts +0 -70
  713. package/dist/core/dashboard/types.js +0 -5
  714. package/dist/core/discoverer/index.d.ts +0 -115
  715. package/dist/core/discoverer/index.js +0 -250
  716. package/dist/core/flakiness/index.d.ts +0 -228
  717. package/dist/core/flakiness/index.js +0 -384
  718. package/dist/core/generation/code-formatter.d.ts +0 -111
  719. package/dist/core/generation/code-formatter.js +0 -307
  720. package/dist/core/generation/code-generator.d.ts +0 -144
  721. package/dist/core/generation/code-generator.js +0 -293
  722. package/dist/core/generation/crawler-pack-generator.d.ts +0 -44
  723. package/dist/core/generation/crawler-pack-generator.js +0 -231
  724. package/dist/core/generation/generator.d.ts +0 -40
  725. package/dist/core/generation/generator.js +0 -76
  726. package/dist/core/generation/index.d.ts +0 -32
  727. package/dist/core/generation/index.js +0 -30
  728. package/dist/core/generation/pack-generator.d.ts +0 -107
  729. package/dist/core/generation/pack-generator.js +0 -416
  730. package/dist/core/generation/prompt-builder.d.ts +0 -132
  731. package/dist/core/generation/prompt-builder.js +0 -672
  732. package/dist/core/generation/source-analyzer.d.ts +0 -213
  733. package/dist/core/generation/source-analyzer.js +0 -657
  734. package/dist/core/generation/test-optimizer.d.ts +0 -117
  735. package/dist/core/generation/test-optimizer.js +0 -328
  736. package/dist/core/generation/types.d.ts +0 -214
  737. package/dist/core/generation/types.js +0 -4
  738. package/dist/core/hooks/compose.d.ts +0 -61
  739. package/dist/core/hooks/compose.js +0 -225
  740. package/dist/core/hooks/runner.d.ts +0 -68
  741. package/dist/core/hooks/runner.js +0 -303
  742. package/dist/core/index.d.ts +0 -104
  743. package/dist/core/index.js +0 -91
  744. package/dist/core/pack/migrator.d.ts +0 -51
  745. package/dist/core/pack/migrator.js +0 -304
  746. package/dist/core/pack/validator.d.ts +0 -42
  747. package/dist/core/pack/validator.js +0 -322
  748. package/dist/core/pack-v2/index.d.ts +0 -9
  749. package/dist/core/pack-v2/index.js +0 -8
  750. package/dist/core/pack-v2/loader.d.ts +0 -63
  751. package/dist/core/pack-v2/loader.js +0 -292
  752. package/dist/core/pack-v2/migrator.d.ts +0 -61
  753. package/dist/core/pack-v2/migrator.js +0 -480
  754. package/dist/core/pack-v2/validator.d.ts +0 -61
  755. package/dist/core/pack-v2/validator.js +0 -577
  756. package/dist/core/parallel/index.d.ts +0 -6
  757. package/dist/core/parallel/index.js +0 -6
  758. package/dist/core/parallel/parallel-runner.d.ts +0 -107
  759. package/dist/core/parallel/parallel-runner.js +0 -192
  760. package/dist/core/proof/bundle.d.ts +0 -137
  761. package/dist/core/proof/bundle.js +0 -160
  762. package/dist/core/proof/canonicalize.d.ts +0 -47
  763. package/dist/core/proof/canonicalize.js +0 -105
  764. package/dist/core/proof/index.d.ts +0 -13
  765. package/dist/core/proof/index.js +0 -18
  766. package/dist/core/proof/schema.d.ts +0 -217
  767. package/dist/core/proof/schema.js +0 -263
  768. package/dist/core/proof/signer.d.ts +0 -111
  769. package/dist/core/proof/signer.js +0 -226
  770. package/dist/core/proof/verifier.d.ts +0 -97
  771. package/dist/core/proof/verifier.js +0 -308
  772. package/dist/core/regression/detector.d.ts +0 -107
  773. package/dist/core/regression/detector.js +0 -497
  774. package/dist/core/regression/index.d.ts +0 -9
  775. package/dist/core/regression/index.js +0 -11
  776. package/dist/core/regression/trend-analyzer.d.ts +0 -102
  777. package/dist/core/regression/trend-analyzer.js +0 -345
  778. package/dist/core/regression/types.d.ts +0 -222
  779. package/dist/core/regression/types.js +0 -7
  780. package/dist/core/regression/vault.d.ts +0 -87
  781. package/dist/core/regression/vault.js +0 -289
  782. package/dist/core/repair/engine/fixer.d.ts +0 -24
  783. package/dist/core/repair/engine/fixer.js +0 -226
  784. package/dist/core/repair/engine/suggestion-engine.d.ts +0 -18
  785. package/dist/core/repair/engine/suggestion-engine.js +0 -187
  786. package/dist/core/repair/index.d.ts +0 -10
  787. package/dist/core/repair/index.js +0 -13
  788. package/dist/core/repair/repairer.d.ts +0 -90
  789. package/dist/core/repair/repairer.js +0 -284
  790. package/dist/core/repair/types.d.ts +0 -91
  791. package/dist/core/repair/types.js +0 -6
  792. package/dist/core/repair/utils/error-analyzer.d.ts +0 -28
  793. package/dist/core/repair/utils/error-analyzer.js +0 -264
  794. package/dist/core/reporting/html-reporter.d.ts +0 -119
  795. package/dist/core/reporting/html-reporter.js +0 -737
  796. package/dist/core/reporting/index.d.ts +0 -6
  797. package/dist/core/reporting/index.js +0 -6
  798. package/dist/core/retry/flakiness-integration.d.ts +0 -60
  799. package/dist/core/retry/flakiness-integration.js +0 -228
  800. package/dist/core/retry/index.d.ts +0 -14
  801. package/dist/core/retry/index.js +0 -16
  802. package/dist/core/retry/retry-engine.d.ts +0 -80
  803. package/dist/core/retry/retry-engine.js +0 -296
  804. package/dist/core/retry/types.d.ts +0 -178
  805. package/dist/core/retry/types.js +0 -52
  806. package/dist/core/retry/vault.d.ts +0 -77
  807. package/dist/core/retry/vault.js +0 -304
  808. package/dist/core/runner/e2e-helpers.d.ts +0 -102
  809. package/dist/core/runner/e2e-helpers.js +0 -153
  810. package/dist/core/runner/phase3-runner.d.ts +0 -200
  811. package/dist/core/runner/phase3-runner.js +0 -1041
  812. package/dist/core/secrets/crypto.d.ts +0 -75
  813. package/dist/core/secrets/crypto.js +0 -223
  814. package/dist/core/secrets/manager.d.ts +0 -76
  815. package/dist/core/secrets/manager.js +0 -219
  816. package/dist/core/security/redaction-patterns-extended.d.ts +0 -27
  817. package/dist/core/security/redaction-patterns-extended.js +0 -247
  818. package/dist/core/security/redactor.d.ts +0 -71
  819. package/dist/core/security/redactor.js +0 -279
  820. package/dist/core/self-healing/assertion-healer.d.ts +0 -97
  821. package/dist/core/self-healing/assertion-healer.js +0 -371
  822. package/dist/core/self-healing/engine.d.ts +0 -122
  823. package/dist/core/self-healing/engine.js +0 -538
  824. package/dist/core/self-healing/index.d.ts +0 -10
  825. package/dist/core/self-healing/index.js +0 -11
  826. package/dist/core/self-healing/selector-healer.d.ts +0 -103
  827. package/dist/core/self-healing/selector-healer.js +0 -372
  828. package/dist/core/self-healing/types.d.ts +0 -152
  829. package/dist/core/self-healing/types.js +0 -6
  830. package/dist/core/serve/diagnostics-collector.d.ts +0 -32
  831. package/dist/core/serve/diagnostics-collector.js +0 -149
  832. package/dist/core/serve/health-checker.d.ts +0 -44
  833. package/dist/core/serve/health-checker.js +0 -219
  834. package/dist/core/serve/index.d.ts +0 -8
  835. package/dist/core/serve/index.js +0 -8
  836. package/dist/core/serve/metrics-collector.d.ts +0 -24
  837. package/dist/core/serve/metrics-collector.js +0 -322
  838. package/dist/core/serve/process-manager.d.ts +0 -36
  839. package/dist/core/serve/process-manager.js +0 -213
  840. package/dist/core/serve/server.d.ts +0 -36
  841. package/dist/core/serve/server.js +0 -191
  842. package/dist/core/slo/config.d.ts +0 -107
  843. package/dist/core/slo/config.js +0 -360
  844. package/dist/core/slo/index.d.ts +0 -11
  845. package/dist/core/slo/index.js +0 -15
  846. package/dist/core/slo/sli-calculator.d.ts +0 -92
  847. package/dist/core/slo/sli-calculator.js +0 -364
  848. package/dist/core/slo/slo-tracker.d.ts +0 -148
  849. package/dist/core/slo/slo-tracker.js +0 -379
  850. package/dist/core/slo/types.d.ts +0 -281
  851. package/dist/core/slo/types.js +0 -7
  852. package/dist/core/slo/vault.d.ts +0 -102
  853. package/dist/core/slo/vault.js +0 -427
  854. package/dist/core/tui/index.d.ts +0 -7
  855. package/dist/core/tui/index.js +0 -6
  856. package/dist/core/tui/monitor.d.ts +0 -92
  857. package/dist/core/tui/monitor.js +0 -271
  858. package/dist/core/tui/renderer.d.ts +0 -33
  859. package/dist/core/tui/renderer.js +0 -218
  860. package/dist/core/tui/types.d.ts +0 -63
  861. package/dist/core/tui/types.js +0 -5
  862. package/dist/core/types/pack-v1.d.ts +0 -251
  863. package/dist/core/types/pack-v1.js +0 -5
  864. package/dist/core/types/pack-v2.d.ts +0 -425
  865. package/dist/core/types/pack-v2.js +0 -8
  866. package/dist/core/types/trust-score.d.ts +0 -69
  867. package/dist/core/types/trust-score.js +0 -191
  868. package/dist/core/vault/cas.d.ts +0 -90
  869. package/dist/core/vault/cas.js +0 -261
  870. package/dist/core/vault/index.d.ts +0 -326
  871. package/dist/core/vault/index.js +0 -1042
  872. package/dist/core/visual/index.d.ts +0 -6
  873. package/dist/core/visual/index.js +0 -6
  874. package/dist/core/visual/visual-regression.d.ts +0 -113
  875. package/dist/core/visual/visual-regression.js +0 -236
  876. package/dist/core/watch/index.d.ts +0 -7
  877. package/dist/core/watch/index.js +0 -6
  878. package/dist/core/watch/watch-mode.d.ts +0 -213
  879. package/dist/core/watch/watch-mode.js +0 -389
  880. package/dist/generators/index.d.ts +0 -5
  881. package/dist/generators/index.js +0 -5
  882. package/dist/generators/json-reporter.d.ts +0 -10
  883. package/dist/generators/json-reporter.js +0 -12
  884. package/dist/generators/test-generator.d.ts +0 -18
  885. package/dist/generators/test-generator.js +0 -78
  886. package/dist/index.d.ts +0 -8
  887. package/dist/index.js +0 -246
  888. package/dist/scanners/dom-scanner.d.ts +0 -52
  889. package/dist/scanners/dom-scanner.js +0 -296
  890. package/dist/scanners/index.d.ts +0 -4
  891. package/dist/scanners/index.js +0 -4
  892. package/dist/schemas/pack.schema.json +0 -236
  893. package/dist/types/scan.d.ts +0 -68
  894. package/dist/types/scan.js +0 -4
  895. package/dist/utils/config.d.ts +0 -5
  896. package/dist/utils/config.js +0 -136
  897. /package/{bin → cli/bin}/qa360.js +0 -0
  898. /package/{examples → cli/examples}/accessibility.yml +0 -0
  899. /package/{examples → cli/examples}/api-basic.yml +0 -0
  900. /package/{examples → cli/examples}/complete.yml +0 -0
  901. /package/{examples → cli/examples}/crawler.yml +0 -0
  902. /package/{examples → cli/examples}/fullstack.yml +0 -0
  903. /package/{examples → cli/examples}/security.yml +0 -0
  904. /package/{examples → cli/examples}/ui-advanced.yml +0 -0
  905. /package/{examples → cli/examples}/ui-basic.yml +0 -0
  906. /package/{dist/core → core}/schemas/pack.schema.json +0 -0
@@ -0,0 +1,1236 @@
1
+ /**
2
+ * QA360 Phase 3 Runner
3
+ * Orchestrates hooks, adapters, and proof generation
4
+ * Supports both Pack v1 and Pack v2 configurations
5
+ */
6
+
7
+ import { existsSync, writeFileSync, mkdirSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { createHash } from 'crypto';
10
+ import chalk from 'chalk';
11
+ import { PackConfigV1 } from '../types/pack-v1.js';
12
+ import { PackConfigV2, AuthConfigV2, GateConfigV2 } from '../types/pack-v2.js';
13
+ import { HooksRunner } from '../hooks/runner.js';
14
+ import { PlaywrightNativeApiAdapter } from '../adapters/playwright-native-api.js';
15
+ import { PlaywrightUiAdapter } from '../adapters/playwright-ui.js';
16
+ import { K6PerfAdapter } from '../adapters/k6-perf.js';
17
+ import { SemgrepSastAdapter } from '../adapters/semgrep-sast.js';
18
+ import { SecurityRedactor } from '../security/redactor.js';
19
+ import { initializeKeys, sign, KeyPair } from '../proof/signer.js';
20
+ import { canonicalize } from '../proof/canonicalize.js';
21
+ import { EvidenceVault, RunRecord, GateRecord, FindingRecord } from '../vault/index.js';
22
+ import { AuthManager, AuthConfig, AuthCredentials } from '../auth/index.js';
23
+ import {
24
+ FlakinessDetector,
25
+ TestResult as FlakyTestResult,
26
+ FlakinessResult,
27
+ FlakinessCategory,
28
+ formatFlakinessScore,
29
+ generateTestId,
30
+ DEFAULT_FLAKINESS_OPTIONS
31
+ } from '../flakiness/index.js';
32
+
33
+ export type PackConfig = PackConfigV1 | PackConfigV2;
34
+
35
+ export interface Phase3RunnerOptions {
36
+ workingDir: string;
37
+ pack: PackConfig;
38
+ outputDir?: string;
39
+ /** Enable flakiness detection (runs tests N times consecutively) */
40
+ flakyDetect?: boolean;
41
+ /** Number of consecutive runs for flakiness detection (default: 3) */
42
+ flakyRuns?: number;
43
+ }
44
+
45
+ export interface GateResult {
46
+ gate: string;
47
+ success: boolean;
48
+ duration: number;
49
+ adapter: string;
50
+ results: any;
51
+ junit?: string;
52
+ error?: string;
53
+ }
54
+
55
+ export interface Phase3RunResult {
56
+ success: boolean;
57
+ pack: PackConfig;
58
+ duration: number;
59
+ gates: GateResult[];
60
+ hooks: {
61
+ beforeAll: any[];
62
+ beforeEach: any[];
63
+ afterEach: any[];
64
+ afterAll: any[];
65
+ };
66
+ summary: {
67
+ total: number;
68
+ passed: number;
69
+ failed: number;
70
+ trustScore: number;
71
+ };
72
+ /** Flakiness analysis results (if enabled) */
73
+ flakiness?: FlakinessResult[];
74
+ proofPath?: string;
75
+ /** Vault run ID for this execution */
76
+ runId?: string;
77
+ error?: string;
78
+ }
79
+
80
+ export class Phase3Runner {
81
+ private workingDir: string;
82
+ private pack: PackConfig;
83
+ private outputDir: string;
84
+ private redactor: SecurityRedactor;
85
+ private hooksRunner: HooksRunner;
86
+ private keyPair?: KeyPair;
87
+ private vault?: EvidenceVault;
88
+ private authManager: AuthManager;
89
+ private authCredentialsCache = new Map<string, AuthCredentials>();
90
+ private flakyDetect: boolean;
91
+ private flakyRuns: number;
92
+ private flakinessDetector: FlakinessDetector;
93
+
94
+ constructor(options: Phase3RunnerOptions) {
95
+ this.workingDir = options.workingDir;
96
+ this.pack = options.pack;
97
+ this.outputDir = options.outputDir || join(this.workingDir, '.qa360', 'runs');
98
+ this.redactor = SecurityRedactor.forLogs();
99
+ this.authManager = new AuthManager();
100
+ this.flakyDetect = options.flakyDetect || false;
101
+ this.flakyRuns = options.flakyRuns || DEFAULT_FLAKINESS_OPTIONS.consecutiveRuns;
102
+ this.flakinessDetector = new FlakinessDetector({
103
+ consecutiveRuns: this.flakyRuns,
104
+ minRuns: 2,
105
+ enablePatternDetection: true
106
+ });
107
+
108
+ // Initialize hooks runner (convert v2 hooks to v1 format if needed)
109
+ const hooks = this.isPackV2(options.pack)
110
+ ? this.convertV2HooksToV1(options.pack.hooks)
111
+ : options.pack.hooks;
112
+
113
+ this.hooksRunner = new HooksRunner({
114
+ workingDir: this.workingDir,
115
+ hooks: hooks || {},
116
+ execution: this.isPackV2(options.pack) ? this.convertV2ExecutionToV1(options.pack.execution) : options.pack.execution,
117
+ redactor: this.redactor
118
+ });
119
+
120
+ // Register auth profiles from pack v2
121
+ if (this.isPackV2(options.pack) && options.pack.auth?.profiles) {
122
+ this.registerAuthProfiles(options.pack.auth.profiles);
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Type guard to check if pack is v2
128
+ */
129
+ private isPackV2(pack: PackConfig): pack is PackConfigV2 {
130
+ return (pack as PackConfigV2).version === 2;
131
+ }
132
+
133
+ /**
134
+ * Register authentication profiles from pack config
135
+ */
136
+ private registerAuthProfiles(profiles: Record<string, any>): void {
137
+ for (const [name, profile] of Object.entries(profiles)) {
138
+ // Convert v2 auth profile to auth module format
139
+ const authConfig: AuthConfig = {
140
+ type: profile.type || 'none',
141
+ ...profile.config
142
+ };
143
+ this.authManager.registerProfile(name, authConfig);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Get auth profile name for a specific gate
149
+ */
150
+ private getAuthProfileForGate(gateName: string): string | undefined {
151
+ if (!this.isPackV2(this.pack) || !this.pack.auth) {
152
+ return undefined;
153
+ }
154
+
155
+ const authConfig = this.pack.auth as AuthConfigV2;
156
+
157
+ // Check if gate has specific auth override
158
+ const gateConfig = (this.pack.gates as Record<string, GateConfigV2>)[gateName];
159
+ if (gateConfig?.auth) {
160
+ return gateConfig.auth;
161
+ }
162
+
163
+ // Use default based on gate type
164
+ if (gateName === 'api_smoke' || gateName === 'api') {
165
+ return authConfig.api;
166
+ }
167
+ if (gateName === 'ui' || gateName === 'a11y') {
168
+ return authConfig.ui;
169
+ }
170
+
171
+ return undefined;
172
+ }
173
+
174
+ /**
175
+ * Authenticate and get credentials for a gate
176
+ */
177
+ private async getCredentialsForGate(gateName: string): Promise<AuthCredentials | undefined> {
178
+ const profileName = this.getAuthProfileForGate(gateName);
179
+
180
+ if (!profileName) {
181
+ return undefined;
182
+ }
183
+
184
+ // Check cache first
185
+ if (this.authCredentialsCache.has(profileName)) {
186
+ return this.authCredentialsCache.get(profileName);
187
+ }
188
+
189
+ // Authenticate
190
+ const result = await this.authManager.authenticate(profileName);
191
+
192
+ if (result.success && result.credentials) {
193
+ this.authCredentialsCache.set(profileName, result.credentials);
194
+ return result.credentials;
195
+ }
196
+
197
+ console.log(chalk.yellow(` ⚠️ Auth failed for profile '${profileName}': ${result.error}`));
198
+ return undefined;
199
+ }
200
+
201
+ /**
202
+ * Convert v2 hooks to v1 format
203
+ */
204
+ private convertV2HooksToV1(hooks?: any): any {
205
+ if (!hooks) return undefined;
206
+
207
+ // v2 hooks use { type, command, ... } format
208
+ // v1 hooks use { run, timeout } format
209
+ const converted: any = {
210
+ beforeAll: [],
211
+ afterAll: [],
212
+ beforeEach: [],
213
+ afterEach: []
214
+ };
215
+
216
+ for (const [phase, phaseHooks] of Object.entries(hooks)) {
217
+ if (Array.isArray(phaseHooks)) {
218
+ converted[phase] = (phaseHooks as any[]).map((h: any) => {
219
+ if (h.type === 'run' || h.type === 'script') {
220
+ return { run: h.command, timeout: h.timeout, cwd: h.cwd, env: h.env };
221
+ }
222
+ if (h.type === 'wait_on') {
223
+ return { run: `npx wait-on ${h.wait_for?.resource || h.command}`, timeout: h.timeout };
224
+ }
225
+ if (h.type === 'docker') {
226
+ return { run: `docker compose ${h.compose?.command || 'up -d'}`, timeout: h.timeout };
227
+ }
228
+ return h;
229
+ });
230
+ }
231
+ }
232
+
233
+ return converted;
234
+ }
235
+
236
+ /**
237
+ * Convert v2 execution config to v1 format
238
+ */
239
+ private convertV2ExecutionToV1(execution?: any): any {
240
+ if (!execution) return undefined;
241
+
242
+ return {
243
+ timeout: execution.default_timeout || execution.timeout,
244
+ max_retries: execution.default_retries || execution.retries,
245
+ on_failure: execution.on_failure || 'continue'
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Get gates array from pack (handles v1 and v2)
251
+ */
252
+ private getGatesArray(): string[] {
253
+ if (this.isPackV2(this.pack)) {
254
+ return Object.keys(this.pack.gates).filter(gateName => {
255
+ const gateConfig = (this.pack.gates as Record<string, GateConfigV2>)[gateName];
256
+ return gateConfig?.enabled !== false;
257
+ });
258
+ }
259
+ return (this.pack as PackConfigV1).gates || [];
260
+ }
261
+
262
+ /**
263
+ * Execute complete Phase 3 workflow
264
+ */
265
+ async run(): Promise<Phase3RunResult> {
266
+ const startTime = Date.now();
267
+
268
+ const gatesArray = this.getGatesArray();
269
+
270
+ console.log(chalk.bold.blue(`\n🚀 QA360 Phase 3 Runner - ${this.pack.name}`));
271
+ console.log(chalk.gray(`Gates: ${gatesArray.join(', ')}`));
272
+
273
+ try {
274
+ // Ensure output directory exists
275
+ this.ensureOutputDir();
276
+
277
+ // Initialize cryptographic keys
278
+ console.log(chalk.blue('\n🔑 Initializing Ed25519 keys...'));
279
+ this.keyPair = await initializeKeys();
280
+ console.log(chalk.green(' ✅ Keys ready'));
281
+
282
+ // Initialize Evidence Vault
283
+ console.log(chalk.blue('\n🗄️ Initializing Evidence Vault...'));
284
+ const vaultDir = join(this.workingDir, '.qa360');
285
+ this.vault = await EvidenceVault.open(vaultDir);
286
+ console.log(chalk.green(' ✅ Vault ready'));
287
+
288
+ // Execute beforeAll hooks
289
+ console.log(chalk.blue('\n🔗 Phase 1: Setup Hooks'));
290
+ const beforeAllResults = await this.hooksRunner.executeHooks('beforeAll');
291
+
292
+ // Check if setup failed and should stop
293
+ const setupFailed = beforeAllResults.some(r => !r.success);
294
+ if (setupFailed && this.pack.execution?.on_failure === 'stop') {
295
+ throw new Error('Setup hooks failed, stopping execution');
296
+ }
297
+
298
+ // Execute gates
299
+ console.log(chalk.blue('\n🎯 Phase 2: Quality Gates'));
300
+ const gateResults: GateResult[] = [];
301
+
302
+ for (const gate of gatesArray) {
303
+ const gateResult = await this.executeGate(gate);
304
+ gateResults.push(gateResult);
305
+
306
+ // Check if gate failed and should stop
307
+ if (!gateResult.success && this.pack.execution?.on_failure === 'stop') {
308
+ console.log(chalk.yellow(`🛑 Gate ${gate} failed, stopping execution`));
309
+ break;
310
+ }
311
+ }
312
+
313
+ // Flakiness Detection Phase (Vision 2.0)
314
+ let flakinessResults: FlakinessResult[] | undefined;
315
+ if (this.flakyDetect) {
316
+ console.log(chalk.blue(`\n🎲 Phase 2.5: Flakiness Detection (${this.flakyRuns} consecutive runs)`));
317
+ flakinessResults = await this.detectFlakiness(gateResults);
318
+
319
+ // Display flakiness summary
320
+ const unstableCount = flakinessResults.filter(f =>
321
+ f.category === FlakinessCategory.UNSTABLE || f.category === FlakinessCategory.SHAKY
322
+ ).length;
323
+
324
+ if (unstableCount > 0) {
325
+ console.log(chalk.yellow(` ⚠️ ${unstableCount} test(s) show flaky behavior`));
326
+ } else {
327
+ console.log(chalk.green(' ✅ All tests stable - no flakiness detected'));
328
+ }
329
+ }
330
+
331
+ // Execute afterAll hooks
332
+ console.log(chalk.blue('\n🔗 Phase 3: Cleanup Hooks'));
333
+ const afterAllResults = await this.hooksRunner.executeHooks('afterAll');
334
+
335
+ // Calculate results
336
+ const duration = Date.now() - startTime;
337
+ const summary = this.calculateSummary(gateResults);
338
+ const success = summary.failed === 0;
339
+
340
+ // Generate proof
341
+ console.log(chalk.blue('\n📋 Phase 4: Proof Generation'));
342
+ const proofPath = await this.generateProof({
343
+ success,
344
+ pack: this.pack,
345
+ duration,
346
+ gates: gateResults,
347
+ hooks: {
348
+ beforeAll: beforeAllResults,
349
+ beforeEach: [],
350
+ afterEach: [],
351
+ afterAll: afterAllResults
352
+ },
353
+ summary
354
+ });
355
+
356
+ // Save to Evidence Vault
357
+ console.log(chalk.blue('\n💾 Phase 5: Evidence Storage'));
358
+ const proofRunId = proofPath.split('/').pop()?.replace('-proof.json', '') || 'unknown';
359
+ const vaultRunId = await this.saveToVault(proofRunId, {
360
+ success,
361
+ pack: this.pack,
362
+ duration,
363
+ gates: gateResults,
364
+ hooks: {
365
+ beforeAll: beforeAllResults,
366
+ beforeEach: [],
367
+ afterEach: [],
368
+ afterAll: afterAllResults
369
+ },
370
+ summary,
371
+ proofPath
372
+ }, proofPath, flakinessResults, startTime);
373
+
374
+ // Final summary
375
+ console.log(chalk.blue('\n📊 Execution Summary'));
376
+ console.log(` Duration: ${duration}ms`);
377
+ console.log(` Gates: ${summary.passed}/${summary.total} passed`);
378
+ console.log(` Trust Score: ${summary.trustScore}%`);
379
+ console.log(` Proof: ${proofPath}`);
380
+
381
+ // Display flakiness details if enabled
382
+ if (flakinessResults && flakinessResults.length > 0) {
383
+ console.log(chalk.blue('\n🎲 Flakiness Scores:'));
384
+ for (const f of flakinessResults) {
385
+ const scoreFormatted = formatFlakinessScore(f.score);
386
+ const categoryMeta = {
387
+ [FlakinessCategory.LEGENDARY]: { emoji: '🟢', color: chalk.green },
388
+ [FlakinessCategory.SOLID]: { emoji: '🟢', color: chalk.green },
389
+ [FlakinessCategory.GOOD]: { emoji: '🟡', color: chalk.yellow },
390
+ [FlakinessCategory.SHAKY]: { emoji: '🟠', color: chalk.hex('#F97316') },
391
+ [FlakinessCategory.UNSTABLE]: { emoji: '🔴', color: chalk.red }
392
+ }[f.category];
393
+
394
+ console.log(` ${categoryMeta.color(`${f.testName}: ${scoreFormatted}`)} (${f.successfulRuns}/${f.totalRuns} passes)`);
395
+ if (f.suggestedFix) {
396
+ console.log(chalk.gray(` 💡 ${f.suggestedFix}`));
397
+ }
398
+ }
399
+ }
400
+
401
+ if (success) {
402
+ console.log(chalk.green('\n✅ All quality gates passed!'));
403
+ } else {
404
+ console.log(chalk.red(`\n❌ ${summary.failed} quality gate(s) failed`));
405
+ }
406
+
407
+ return {
408
+ success,
409
+ pack: this.pack,
410
+ duration,
411
+ gates: gateResults,
412
+ hooks: {
413
+ beforeAll: beforeAllResults,
414
+ beforeEach: [],
415
+ afterEach: [],
416
+ afterAll: afterAllResults
417
+ },
418
+ summary,
419
+ flakiness: flakinessResults,
420
+ proofPath,
421
+ runId: vaultRunId
422
+ };
423
+
424
+ } catch (error) {
425
+ const duration = Date.now() - startTime;
426
+
427
+ // Ensure cleanup even on error
428
+ try {
429
+ await this.hooksRunner.executeHooks('afterAll');
430
+ } catch {
431
+ // Ignore cleanup errors
432
+ }
433
+
434
+ return {
435
+ success: false,
436
+ pack: this.pack,
437
+ duration,
438
+ gates: [],
439
+ hooks: { beforeAll: [], beforeEach: [], afterEach: [], afterAll: [] },
440
+ summary: { total: 0, passed: 0, failed: 0, trustScore: 0 },
441
+ error: this.redactor.redact(error instanceof Error ? error.message : 'Unknown error')
442
+ };
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Execute a single quality gate
448
+ */
449
+ private async executeGate(gate: string): Promise<GateResult> {
450
+ const startTime = Date.now();
451
+
452
+ console.log(chalk.cyan(`\n 🎯 Gate: ${gate}`));
453
+
454
+ try {
455
+ let result: any;
456
+ let adapter: string;
457
+
458
+ // Check if this is a v2 pack with dynamic gate configuration
459
+ if (this.isPackV2(this.pack)) {
460
+ const gateConfig = (this.pack.gates as Record<string, any>)[gate];
461
+ if (gateConfig) {
462
+ return await this.executeDynamicGate(gate, gateConfig);
463
+ }
464
+ }
465
+
466
+ // Legacy v1 gates or predefined gates
467
+ switch (gate) {
468
+ case 'api_smoke':
469
+ adapter = 'playwright-native-api';
470
+ result = await this.runApiSmokeGate();
471
+ break;
472
+
473
+ case 'ui':
474
+ adapter = 'playwright-ui';
475
+ result = await this.runUiGate();
476
+ break;
477
+
478
+ case 'a11y':
479
+ adapter = 'playwright-ui';
480
+ result = await this.runA11yGate();
481
+ break;
482
+
483
+ case 'perf':
484
+ adapter = 'k6';
485
+ result = await this.runPerfGate();
486
+ break;
487
+
488
+ case 'sast':
489
+ adapter = 'semgrep';
490
+ result = await this.runSastGate();
491
+ break;
492
+
493
+ case 'dast':
494
+ adapter = 'zap';
495
+ result = await this.runDastGate();
496
+ break;
497
+
498
+ default:
499
+ throw new Error(`Unknown gate: ${gate}`);
500
+ }
501
+
502
+ const duration = Date.now() - startTime;
503
+
504
+ if (result.success) {
505
+ console.log(chalk.green(` ✅ ${gate} passed (${duration}ms)`));
506
+ } else {
507
+ console.log(chalk.red(` ❌ ${gate} failed (${duration}ms)`));
508
+ if (result.error) {
509
+ console.log(chalk.red(` 🔍 ${result.error}`));
510
+ }
511
+ }
512
+
513
+ return {
514
+ gate,
515
+ success: result.success,
516
+ duration,
517
+ adapter,
518
+ results: result,
519
+ junit: result.junit,
520
+ error: result.error
521
+ };
522
+
523
+ } catch (error) {
524
+ const duration = Date.now() - startTime;
525
+ const errorMessage = this.redactor.redact(error instanceof Error ? error.message : 'Unknown error');
526
+
527
+ console.log(chalk.red(` 💥 ${gate} crashed (${duration}ms): ${errorMessage}`));
528
+
529
+ return {
530
+ gate,
531
+ success: false,
532
+ duration,
533
+ adapter: 'unknown',
534
+ results: null,
535
+ error: errorMessage
536
+ };
537
+ }
538
+ }
539
+
540
+ /**
541
+ * Execute a dynamic v2 gate
542
+ */
543
+ private async executeDynamicGate(gateName: string, gateConfig: any): Promise<GateResult> {
544
+ const startTime = Date.now();
545
+ const adapterType = gateConfig.adapter || gateConfig.type;
546
+
547
+ if (!adapterType) {
548
+ throw new Error(`Gate '${gateName}' must specify an adapter`);
549
+ }
550
+
551
+ // Get auth credentials for this gate
552
+ const credentials = await this.getCredentialsForGate(gateName);
553
+
554
+ // Map adapter type to implementation
555
+ let result: GateResult;
556
+ switch (adapterType) {
557
+ case 'playwright-api':
558
+ result = await this.executePlaywrightApiGate(gateName, gateConfig, credentials);
559
+ break;
560
+
561
+ case 'playwright-ui':
562
+ result = await this.executePlaywrightUiGate(gateName, gateConfig, credentials);
563
+ break;
564
+
565
+ case 'k6':
566
+ case 'k6-perf':
567
+ result = await this.executeK6PerfGate(gateName, gateConfig);
568
+ break;
569
+
570
+ case 'semgrep':
571
+ case 'sast':
572
+ result = await this.executeSemgrepSastGate(gateName, gateConfig);
573
+ break;
574
+
575
+ default:
576
+ throw new Error(`Unsupported adapter: '${adapterType}' for gate '${gateName}'`);
577
+ }
578
+
579
+ // Set duration
580
+ result.duration = Date.now() - startTime;
581
+
582
+ // Log result
583
+ if (result.success) {
584
+ console.log(chalk.green(` ✅ ${gateName} passed (${result.duration}ms)`));
585
+ } else {
586
+ console.log(chalk.red(` ❌ ${gateName} failed (${result.duration}ms)`));
587
+ if (result.error) {
588
+ console.log(chalk.red(` 🔍 ${result.error}`));
589
+ }
590
+ }
591
+
592
+ return result;
593
+ }
594
+
595
+ /**
596
+ * Execute Playwright API gate with v2 config
597
+ * Uses PlaywrightNativeApiAdapter for zero-overhead HTTP testing
598
+ */
599
+ private async executePlaywrightApiGate(gateName: string, gateConfig: any, credentials?: any): Promise<GateResult> {
600
+ const { PlaywrightNativeApiAdapter } = await import('../adapters/playwright-native-api.js');
601
+ const adapter = new PlaywrightNativeApiAdapter();
602
+
603
+ // Transform v2 config to adapter format
604
+ const gateConfigData = gateConfig.config || {};
605
+ const gateOptions = gateConfig.options || {};
606
+
607
+ const config = {
608
+ target: {
609
+ baseUrl: gateConfigData.baseUrl,
610
+ smoke: gateConfigData.smoke
611
+ },
612
+ budgets: gateConfigData.budgets,
613
+ timeout: gateOptions.timeout || gateConfigData.timeout,
614
+ retries: gateOptions.retries || gateConfigData.retries,
615
+ auth: credentials
616
+ };
617
+
618
+ const result = await adapter.runSmokeTests(config);
619
+ return {
620
+ gate: gateName,
621
+ success: result.success,
622
+ duration: 0, // Will be set by caller
623
+ adapter: 'playwright-native-api',
624
+ results: result,
625
+ junit: result.junit
626
+ };
627
+ }
628
+
629
+ /**
630
+ * Execute Playwright UI gate with v2 config
631
+ */
632
+ private async executePlaywrightUiGate(gateName: string, gateConfig: any, credentials?: any): Promise<GateResult> {
633
+ const { PlaywrightUiAdapter } = await import('../adapters/playwright-ui.js');
634
+ const adapter = new PlaywrightUiAdapter();
635
+
636
+ // Transform v2 config to adapter format
637
+ // v2: { baseUrl, pages: [{ url: '/', expectedElements: [...] }] }
638
+ // adapter expects: { target: { baseUrl, pages: ['https://.../'] } }
639
+ const gateConfigData = gateConfig.config || {};
640
+ const gateOptions = gateConfig.options || {};
641
+
642
+ // Transform page objects to full URLs
643
+ // v2 pages format: [{ url: '/', expectedElements: [...] }] or ['/', '/about']
644
+ const rawPages = gateConfigData.pages;
645
+ let pages: string[] | undefined;
646
+ if (rawPages && Array.isArray(rawPages) && rawPages.length > 0) {
647
+ const baseUrl = gateConfigData.baseUrl || '';
648
+ pages = rawPages.map((p: any) => {
649
+ if (typeof p === 'string') {
650
+ // Already a URL string - make it absolute if relative
651
+ return p.startsWith('http') ? p : `${baseUrl.replace(/\/$/, '')}${p}`;
652
+ } else if (p && typeof p === 'object' && p.url) {
653
+ // Page object { url: '/', ... } - convert to full URL
654
+ const url = p.url;
655
+ return url.startsWith('http') ? url : `${baseUrl.replace(/\/$/, '')}${url}`;
656
+ }
657
+ return p;
658
+ });
659
+ } else if (gateConfigData.baseUrl) {
660
+ pages = [gateConfigData.baseUrl];
661
+ }
662
+
663
+ const config = {
664
+ target: {
665
+ baseUrl: gateConfigData.baseUrl,
666
+ pages: pages
667
+ },
668
+ budgets: gateConfigData.budgets,
669
+ timeout: gateOptions.timeout || gateConfigData.timeout,
670
+ auth: credentials,
671
+ // Playwright++ features
672
+ artifacts: gateConfigData.artifacts,
673
+ htmlReport: gateConfigData.htmlReport,
674
+ bail: gateConfigData.bail
675
+ };
676
+
677
+ const result = await adapter.runSmokeTests(config);
678
+ return {
679
+ gate: gateName,
680
+ success: result.success,
681
+ duration: 0, // Will be set by caller
682
+ adapter: 'playwright-ui',
683
+ results: result,
684
+ junit: result.junit
685
+ };
686
+ }
687
+
688
+ /**
689
+ * Execute K6 Performance gate with v2 config
690
+ */
691
+ private async executeK6PerfGate(gateName: string, gateConfig: any): Promise<GateResult> {
692
+ const { K6PerfAdapter } = await import('../adapters/k6-perf.js');
693
+ const adapter = new K6PerfAdapter(this.workingDir);
694
+
695
+ const config = {
696
+ baseUrl: gateConfig.config?.baseUrl,
697
+ ...gateConfig.config
698
+ };
699
+
700
+ const result = await adapter.runPerfTest(config);
701
+ return {
702
+ gate: gateName,
703
+ success: result.success,
704
+ duration: 0,
705
+ adapter: 'k6',
706
+ results: result,
707
+ junit: result.junit
708
+ };
709
+ }
710
+
711
+ /**
712
+ * Execute Semgrep SAST gate with v2 config
713
+ */
714
+ private async executeSemgrepSastGate(gateName: string, gateConfig: any): Promise<GateResult> {
715
+ const { SemgrepSastAdapter } = await import('../adapters/semgrep-sast.js');
716
+ const adapter = new SemgrepSastAdapter();
717
+
718
+ const config = {
719
+ workingDir: this.workingDir,
720
+ ...gateConfig.config
721
+ };
722
+
723
+ const result = await adapter.runSastScan(config);
724
+ return {
725
+ gate: gateName,
726
+ success: result.success,
727
+ duration: 0,
728
+ adapter: 'semgrep',
729
+ results: result,
730
+ junit: result.junit
731
+ };
732
+ }
733
+
734
+ /**
735
+ * Run API smoke gate
736
+ * Uses PlaywrightNativeApiAdapter for zero-overhead HTTP testing
737
+ */
738
+ private async runApiSmokeGate() {
739
+ const target = this.getTargetApi();
740
+ if (!target) {
741
+ throw new Error('API smoke gate requires targets.api configuration or gate config with baseUrl');
742
+ }
743
+
744
+ const credentials = await this.getCredentialsForGate('api_smoke');
745
+
746
+ const adapter = new PlaywrightNativeApiAdapter();
747
+ return await adapter.runSmokeTests({
748
+ target,
749
+ budgets: this.getBudgets(),
750
+ timeout: this.getExecutionTimeout() || 10000,
751
+ retries: this.getExecutionRetries() || 1,
752
+ auth: credentials
753
+ });
754
+ }
755
+
756
+ /**
757
+ * Run UI gate (includes basic accessibility)
758
+ */
759
+ private async runUiGate() {
760
+ const target = this.getTargetWeb();
761
+ if (!target) {
762
+ throw new Error('UI gate requires targets.web configuration or gate config with baseUrl');
763
+ }
764
+
765
+ const credentials = await this.getCredentialsForGate('ui');
766
+
767
+ const adapter = new PlaywrightUiAdapter();
768
+ return await adapter.runSmokeTests({
769
+ target,
770
+ budgets: this.getBudgets(),
771
+ timeout: this.getExecutionTimeout() || 30000,
772
+ auth: credentials
773
+ });
774
+ }
775
+
776
+ /**
777
+ * Run A11y gate (focused accessibility testing)
778
+ */
779
+ private async runA11yGate() {
780
+ // Same as UI gate but focused on accessibility
781
+ return await this.runUiGate();
782
+ }
783
+
784
+ /**
785
+ * Run performance gate
786
+ */
787
+ private async runPerfGate() {
788
+ const baseUrl = (this.pack as PackConfigV1).targets?.web?.baseUrl || (this.pack as PackConfigV1).targets?.api?.baseUrl;
789
+ if (!baseUrl) {
790
+ throw new Error('Performance gate requires web or api target');
791
+ }
792
+
793
+ const adapter = new K6PerfAdapter(this.workingDir);
794
+ return await adapter.runPerfTest({
795
+ baseUrl,
796
+ budgets: (this.pack as PackConfigV1).budgets,
797
+ duration: '30s',
798
+ vus: 5,
799
+ timeout: 120000
800
+ });
801
+ }
802
+
803
+ /**
804
+ * Run SAST gate
805
+ */
806
+ private async runSastGate() {
807
+ const adapter = new SemgrepSastAdapter();
808
+ return await adapter.runSastScan({
809
+ workingDir: this.workingDir,
810
+ security: (this.pack as PackConfigV1).security,
811
+ rules: ['auto'],
812
+ paths: ['src/', 'lib/', '.'],
813
+ timeout: 120000
814
+ });
815
+ }
816
+
817
+ /**
818
+ * Run DAST gate (mock implementation)
819
+ */
820
+ private async runDastGate() {
821
+ // Mock DAST implementation for Phase 3
822
+ console.log(chalk.yellow(' ⚠️ DAST gate: Mock implementation (ZAP integration in Phase 4)'));
823
+
824
+ return {
825
+ success: true,
826
+ findings: [],
827
+ summary: { total: 0, high: 0, medium: 0, low: 0 },
828
+ junit: `<?xml version="1.0" encoding="UTF-8"?>
829
+ <testsuite name="DAST Mock" tests="1" failures="0" time="0">
830
+ <testcase name="Mock DAST Scan" time="0"></testcase>
831
+ </testsuite>`
832
+ };
833
+ }
834
+
835
+ /**
836
+ * Calculate execution summary
837
+ */
838
+ private calculateSummary(gateResults: GateResult[]): Phase3RunResult['summary'] {
839
+ const total = gateResults.length;
840
+ const passed = gateResults.filter(g => g.success).length;
841
+ const failed = total - passed;
842
+
843
+ // Calculate trust score (weighted by gate importance)
844
+ const gateWeights: Record<string, number> = {
845
+ 'api_smoke': 20,
846
+ 'ui': 15,
847
+ 'perf': 15,
848
+ 'sast': 20,
849
+ 'dast': 20,
850
+ 'a11y': 10
851
+ };
852
+
853
+ let totalWeight = 0;
854
+ let passedWeight = 0;
855
+
856
+ for (const gate of gateResults) {
857
+ const weight = gateWeights[gate.gate] || 10;
858
+ totalWeight += weight;
859
+ if (gate.success) {
860
+ passedWeight += weight;
861
+ }
862
+ }
863
+
864
+ const trustScore = totalWeight > 0 ? Math.round((passedWeight / totalWeight) * 100) : 0;
865
+
866
+ return { total, passed, failed, trustScore };
867
+ }
868
+
869
+ /**
870
+ * Generate cryptographically signed proof document
871
+ */
872
+ private async generateProof(result: Phase3RunResult): Promise<string> {
873
+ const timestamp = new Date().toISOString();
874
+ const runId = `run-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
875
+
876
+ // Build proof payload (without signature)
877
+ const proofPayload = {
878
+ version: '3.0.0',
879
+ runId,
880
+ timestamp,
881
+ pack: {
882
+ name: result.pack.name,
883
+ version: result.pack.version,
884
+ gates: result.pack.gates
885
+ },
886
+ execution: {
887
+ duration: result.duration,
888
+ success: result.success,
889
+ trustScore: result.summary.trustScore
890
+ },
891
+ gates: result.gates.map(g => {
892
+ const gateObj: any = {
893
+ gate: g.gate,
894
+ adapter: g.adapter,
895
+ success: g.success,
896
+ duration: g.duration
897
+ };
898
+ // Only include error if it exists (avoid undefined fields)
899
+ if (g.error !== undefined) {
900
+ gateObj.error = g.error;
901
+ }
902
+ return gateObj;
903
+ }),
904
+ hooks: {
905
+ beforeAll: result.hooks.beforeAll.length,
906
+ afterAll: result.hooks.afterAll.length
907
+ }
908
+ };
909
+
910
+ // Canonicalize the payload for signing (must match verification: canonical + newline)
911
+ const canonicalPayload = canonicalize(proofPayload) + '\n';
912
+
913
+ // Sign with Ed25519
914
+ let signatureValue: string;
915
+ let algorithm: string;
916
+ let publicKeyB64: string;
917
+
918
+ if (this.keyPair) {
919
+ signatureValue = sign(canonicalPayload, this.keyPair.secretKey);
920
+ algorithm = 'ed25519';
921
+ publicKeyB64 = Buffer.from(this.keyPair.publicKey).toString('base64');
922
+ console.log(chalk.green(' 🔏 Proof signed with Ed25519'));
923
+ } else {
924
+ signatureValue = `unsigned-${runId}`;
925
+ algorithm = 'none';
926
+ publicKeyB64 = '';
927
+ console.log(chalk.yellow(' ⚠️ Proof unsigned (no keys available)'));
928
+ }
929
+
930
+ // Build complete proof with signature
931
+ const proof = {
932
+ ...proofPayload,
933
+ signature: {
934
+ algorithm,
935
+ publicKey: publicKeyB64,
936
+ value: signatureValue,
937
+ timestamp
938
+ }
939
+ };
940
+
941
+ // Save proof
942
+ const proofPath = join(this.outputDir, `${runId}-proof.json`);
943
+ writeFileSync(proofPath, JSON.stringify(proof, null, 2));
944
+
945
+ return proofPath;
946
+ }
947
+
948
+ /**
949
+ * Save run results to Evidence Vault
950
+ * @returns The vault run ID
951
+ */
952
+ private async saveToVault(
953
+ runId: string,
954
+ result: Phase3RunResult,
955
+ proofPath: string,
956
+ flakinessResults?: FlakinessResult[],
957
+ startTime?: number
958
+ ): Promise<string | undefined> {
959
+ if (!this.vault) {
960
+ console.log(chalk.yellow(' ⚠️ Vault not initialized, skipping storage'));
961
+ return undefined;
962
+ }
963
+
964
+ try {
965
+ // Begin run in vault (returns actual runId used)
966
+ // Use startTime if provided to correctly calculate duration
967
+ const { runId: vaultRunId } = await this.vault.beginRun({
968
+ pack_path: `${(this.pack as any).name || 'pack'}.yaml`,
969
+ pack_hash: this.hashPack(result.pack),
970
+ started_at: startTime // Use actual run start time for accurate duration
971
+ });
972
+
973
+ // Finish run with final status
974
+ await this.vault.finishRun(vaultRunId, {
975
+ status: result.success ? 'passed' : 'failed',
976
+ trust_score: result.summary.trustScore,
977
+ signature: this.keyPair ? 'ed25519-signed' : undefined
978
+ });
979
+
980
+ // Record gate executions
981
+ for (const gate of result.gates) {
982
+ await this.vault.recordGate(vaultRunId, {
983
+ name: gate.gate,
984
+ status: gate.success ? 'passed' : 'failed',
985
+ duration_ms: gate.duration,
986
+ metrics_json: JSON.stringify(gate.results?.summary || {})
987
+ });
988
+
989
+ // Record finding if gate has error
990
+ if (gate.error) {
991
+ await this.vault.recordFinding(vaultRunId, {
992
+ gate: gate.gate,
993
+ severity: 'high',
994
+ rule: 'gate-failure',
995
+ message: gate.error
996
+ });
997
+ }
998
+ }
999
+
1000
+ // Record flakiness results if available
1001
+ if (flakinessResults && flakinessResults.length > 0) {
1002
+ for (const flaky of flakinessResults) {
1003
+ // Record unstable/shaky tests as findings
1004
+ if (flaky.category === FlakinessCategory.UNSTABLE || flaky.category === FlakinessCategory.SHAKY) {
1005
+ await this.vault.recordFinding(vaultRunId, {
1006
+ gate: flaky.gate,
1007
+ severity: flaky.category === FlakinessCategory.UNSTABLE ? 'high' : 'medium',
1008
+ rule: 'flaky-test-detected',
1009
+ message: `Test "${flaky.testName}" is ${flaky.category}: ${flaky.score}% reliability (${flaky.successfulRuns}/${flaky.totalRuns} passes)`
1010
+ });
1011
+ }
1012
+ }
1013
+ console.log(chalk.green(` 💾 ${flakinessResults.length} flakiness analysis(es) saved`));
1014
+ }
1015
+
1016
+ console.log(chalk.green(' 💾 Run saved to Evidence Vault'));
1017
+ return vaultRunId;
1018
+
1019
+ } catch (error) {
1020
+ console.log(chalk.yellow(` ⚠️ Failed to save to vault: ${error}`));
1021
+ return undefined;
1022
+ }
1023
+ }
1024
+
1025
+ /**
1026
+ * Detect flakiness by running tests multiple times consecutively
1027
+ * @param gateResults Original gate results from first run
1028
+ * @returns Flakiness analysis results
1029
+ */
1030
+ private async detectFlakiness(gateResults: GateResult[]): Promise<FlakinessResult[]> {
1031
+ const flakinessMap = new Map<string, FlakyTestResult[]>();
1032
+ const timestamp = Date.now();
1033
+
1034
+ // First, collect results from the initial run
1035
+ for (const gateResult of gateResults) {
1036
+ for (const [testId, testResult] of this.extractTestResults(gateResult, timestamp)) {
1037
+ if (!flakinessMap.has(testId)) {
1038
+ flakinessMap.set(testId, []);
1039
+ }
1040
+ flakinessMap.get(testId)!.push(testResult);
1041
+ }
1042
+ }
1043
+
1044
+ // Run additional consecutive runs
1045
+ for (let run = 1; run < this.flakyRuns; run++) {
1046
+ console.log(chalk.gray(` 🔄 Consecutive run ${run + 1}/${this.flakyRuns}...`));
1047
+
1048
+ for (const gateResult of gateResults) {
1049
+ // Re-run all gates to detect flakiness
1050
+ try {
1051
+ const retryResult = await this.executeGate(gateResult.gate);
1052
+
1053
+ // Extract and store test results
1054
+ for (const [testId, testResult] of this.extractTestResults(retryResult, timestamp)) {
1055
+ if (!flakinessMap.has(testId)) {
1056
+ flakinessMap.set(testId, []);
1057
+ }
1058
+ flakinessMap.get(testId)!.push(testResult);
1059
+ }
1060
+ } catch (error) {
1061
+ console.log(chalk.yellow(` ⚠️ Failed to re-run ${gateResult.gate}: ${error}`));
1062
+ }
1063
+ }
1064
+ }
1065
+
1066
+ // Analyze all collected results
1067
+ return this.flakinessDetector.analyzeAll(flakinessMap);
1068
+ }
1069
+
1070
+ /**
1071
+ * Extract test results from a gate result
1072
+ * Returns a map of testId to TestResult for flakiness tracking
1073
+ */
1074
+ private extractTestResults(gateResult: GateResult, timestamp: number): Map<string, FlakyTestResult> {
1075
+ const results = new Map<string, FlakyTestResult>();
1076
+
1077
+ // Extract test results from adapter output
1078
+ const adapterResults = gateResult.results;
1079
+
1080
+ if (adapterResults?.results && Array.isArray(adapterResults.results)) {
1081
+ // Check for Playwright Native API adapter format
1082
+ const firstResult = adapterResults.results[0];
1083
+
1084
+ if (firstResult && 'endpoint' in firstResult && 'method' in firstResult) {
1085
+ // PlaywrightNativeApiAdapter format: { endpoint, method, status, success, error, ... }
1086
+ for (const test of adapterResults.results as Array<{endpoint: string; method: string; status: number; success: boolean; error?: string; responseTime?: number}>) {
1087
+ // Extract just the path from full URL for cleaner test names
1088
+ const url = new URL(test.endpoint);
1089
+ const path = url.pathname + url.search;
1090
+ const testName = `${test.method} ${path} -> ${test.status}`;
1091
+ const testId = generateTestId(testName, gateResult.gate);
1092
+ results.set(testId, {
1093
+ testId,
1094
+ testName,
1095
+ filePath: gateResult.gate,
1096
+ gate: gateResult.gate,
1097
+ success: test.success,
1098
+ durationMs: test.responseTime || 0,
1099
+ errorMessage: test.error,
1100
+ timestamp: timestamp + Math.random(), // Small offset for ordering
1101
+ environment: process.env.NODE_ENV || 'local'
1102
+ });
1103
+ }
1104
+ } else {
1105
+ // Generic adapter format with results array
1106
+ for (const test of adapterResults.results as Array<{name?: string; passed?: boolean; status?: string; duration?: number; error?: {message?: string; type?: string}}>) {
1107
+ const testName = test.name || gateResult.gate;
1108
+ const testId = generateTestId(testName, gateResult.gate);
1109
+ results.set(testId, {
1110
+ testId,
1111
+ testName,
1112
+ filePath: gateResult.gate,
1113
+ gate: gateResult.gate,
1114
+ success: test.passed || test.status === 'passed',
1115
+ durationMs: test.duration || 0,
1116
+ errorType: test.error?.type,
1117
+ errorMessage: test.error?.message,
1118
+ timestamp: timestamp + Math.random(),
1119
+ environment: process.env.NODE_ENV || 'local'
1120
+ });
1121
+ }
1122
+ }
1123
+ } else if (adapterResults?.summary) {
1124
+ // Generic adapter with summary only (no detailed results)
1125
+ const testId = generateTestId(gateResult.gate, gateResult.gate);
1126
+ results.set(testId, {
1127
+ testId,
1128
+ testName: gateResult.gate,
1129
+ filePath: gateResult.gate,
1130
+ gate: gateResult.gate,
1131
+ success: gateResult.success,
1132
+ durationMs: gateResult.duration,
1133
+ errorMessage: gateResult.error,
1134
+ timestamp,
1135
+ environment: process.env.NODE_ENV || 'local'
1136
+ });
1137
+ } else {
1138
+ // Fallback: create single test result from gate
1139
+ const testId = generateTestId(gateResult.gate, gateResult.gate);
1140
+ results.set(testId, {
1141
+ testId,
1142
+ testName: gateResult.gate,
1143
+ filePath: gateResult.gate,
1144
+ gate: gateResult.gate,
1145
+ success: gateResult.success,
1146
+ durationMs: gateResult.duration,
1147
+ errorMessage: gateResult.error,
1148
+ timestamp,
1149
+ environment: process.env.NODE_ENV || 'local'
1150
+ });
1151
+ }
1152
+
1153
+ return results;
1154
+ }
1155
+
1156
+ /**
1157
+ * Generate hash of pack configuration
1158
+ */
1159
+ private hashPack(pack: PackConfig): string {
1160
+ return createHash('sha256')
1161
+ .update(JSON.stringify(pack))
1162
+ .digest('hex')
1163
+ .substring(0, 16);
1164
+ }
1165
+
1166
+ /**
1167
+ * Get API target (v1 or v2 format)
1168
+ */
1169
+ private getTargetApi(): any {
1170
+ if (this.isPackV2(this.pack)) {
1171
+ // In v2, target is in the gate config
1172
+ const gateConfig = this.pack.gates['api_smoke'] || this.pack.gates['api'];
1173
+ if (gateConfig && (gateConfig as any).config?.baseUrl) {
1174
+ return (gateConfig as any).config;
1175
+ }
1176
+ return undefined;
1177
+ }
1178
+ return this.pack.targets?.api;
1179
+ }
1180
+
1181
+ /**
1182
+ * Get Web target (v1 or v2 format)
1183
+ */
1184
+ private getTargetWeb(): any {
1185
+ if (this.isPackV2(this.pack)) {
1186
+ // In v2, target is in the gate config
1187
+ const gateConfig = this.pack.gates['ui'] || this.pack.gates['a11y'];
1188
+ if (gateConfig && (gateConfig as any).config?.baseUrl) {
1189
+ return (gateConfig as any).config;
1190
+ }
1191
+ return undefined;
1192
+ }
1193
+ return this.pack.targets?.web;
1194
+ }
1195
+
1196
+ /**
1197
+ * Get budgets (v1 or v2 format)
1198
+ */
1199
+ private getBudgets(): any {
1200
+ if (this.isPackV2(this.pack)) {
1201
+ // In v2, budgets can be in gate config or global
1202
+ // For now, return undefined - budgets are gate-specific in v2
1203
+ return undefined;
1204
+ }
1205
+ return this.pack.budgets;
1206
+ }
1207
+
1208
+ /**
1209
+ * Get execution timeout (v1 or v2 format)
1210
+ */
1211
+ private getExecutionTimeout(): number | undefined {
1212
+ if (this.isPackV2(this.pack)) {
1213
+ return this.pack.execution?.default_timeout;
1214
+ }
1215
+ return this.pack.execution?.timeout;
1216
+ }
1217
+
1218
+ /**
1219
+ * Get execution retries (v1 or v2 format)
1220
+ */
1221
+ private getExecutionRetries(): number | undefined {
1222
+ if (this.isPackV2(this.pack)) {
1223
+ return this.pack.execution?.default_retries;
1224
+ }
1225
+ return this.pack.execution?.max_retries;
1226
+ }
1227
+
1228
+ /**
1229
+ * Ensure output directory exists
1230
+ */
1231
+ private ensureOutputDir(): void {
1232
+ if (!existsSync(this.outputDir)) {
1233
+ mkdirSync(this.outputDir, { recursive: true });
1234
+ }
1235
+ }
1236
+ }