qa360 2.1.2 → 2.1.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 (866) hide show
  1. package/.BETA_TESTING_FEEDBACK.md +256 -0
  2. package/.claude/settings.local.json +151 -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 +62 -0
  25. package/check-branches.sh +32 -0
  26. package/cli/CHANGELOG.md +84 -0
  27. package/cli/LICENSE +24 -0
  28. package/cli/README.md +222 -0
  29. package/cli/examples/README.md +160 -0
  30. package/cli/package.json +76 -0
  31. package/cli/scripts/bundle-for-npm.sh +51 -0
  32. package/cli/scripts/validate-package.js +116 -0
  33. package/cli/src/__tests__/commands/doctor.test.ts +97 -0
  34. package/cli/src/__tests__/index.test.ts +15 -0
  35. package/cli/src/cli-minimal.ts +44 -0
  36. package/cli/src/commands/__tests__/crawl.test.ts +412 -0
  37. package/cli/src/commands/__tests__/doctor-qa360-home.test.ts +156 -0
  38. package/cli/src/commands/__tests__/e2e-ui-tests.test.ts +494 -0
  39. package/cli/src/commands/__tests__/e2e.test.ts +187 -0
  40. package/cli/src/commands/__tests__/flakiness.test.ts +528 -0
  41. package/cli/src/commands/__tests__/generate.test.ts +507 -0
  42. package/cli/src/commands/__tests__/history.integration.test.ts +358 -0
  43. package/cli/src/commands/__tests__/history.test.ts +433 -0
  44. package/cli/src/commands/__tests__/monitor-realworld.test.ts +199 -0
  45. package/cli/src/commands/__tests__/monitor.test.ts +81 -0
  46. package/cli/src/commands/__tests__/ollama.test.ts +529 -0
  47. package/cli/src/commands/__tests__/repair.test.ts +225 -0
  48. package/cli/src/commands/__tests__/report.integration.test.ts +167 -0
  49. package/cli/src/commands/__tests__/report.test.ts +294 -0
  50. package/cli/src/commands/__tests__/report.vitest.ts +288 -0
  51. package/cli/src/commands/__tests__/retry.test.ts +78 -0
  52. package/cli/src/commands/__tests__/run.integration.test.ts +240 -0
  53. package/cli/src/commands/__tests__/run.test.ts +346 -0
  54. package/cli/src/commands/__tests__/run.vitest.ts +301 -0
  55. package/cli/src/commands/__tests__/secrets.test.ts +114 -0
  56. package/cli/src/commands/__tests__/serve.test.ts +80 -0
  57. package/cli/src/commands/__tests__/verify.test.ts +103 -0
  58. package/cli/src/commands/ai.ts +579 -0
  59. package/cli/src/commands/ask.ts +678 -0
  60. package/cli/src/commands/coverage.ts +305 -0
  61. package/cli/src/commands/crawl.ts +155 -0
  62. package/cli/src/commands/doctor.ts +610 -0
  63. package/cli/src/commands/examples.ts +248 -0
  64. package/cli/src/commands/explain.ts +710 -0
  65. package/cli/src/commands/flakiness.ts +560 -0
  66. package/cli/src/commands/generate.ts +566 -0
  67. package/cli/src/commands/history.ts +914 -0
  68. package/cli/src/commands/init.ts +763 -0
  69. package/cli/src/commands/monitor.ts +270 -0
  70. package/cli/src/commands/ollama.ts +337 -0
  71. package/cli/src/commands/pack.ts +497 -0
  72. package/cli/src/commands/regression.ts +400 -0
  73. package/cli/src/commands/repair.ts +356 -0
  74. package/cli/src/commands/report.ts +463 -0
  75. package/cli/src/commands/retry.ts +380 -0
  76. package/cli/src/commands/run.ts +218 -0
  77. package/cli/src/commands/scan.ts +177 -0
  78. package/cli/src/commands/secrets.ts +340 -0
  79. package/cli/src/commands/serve.ts +194 -0
  80. package/cli/src/commands/slo.ts +387 -0
  81. package/cli/src/commands/verify-temp-note.md +11 -0
  82. package/cli/src/commands/verify.ts +322 -0
  83. package/cli/src/generators/index.ts +6 -0
  84. package/cli/src/generators/json-reporter.ts +15 -0
  85. package/cli/src/generators/test-generator.ts +90 -0
  86. package/cli/src/index.ts +289 -0
  87. package/cli/src/scanners/dom-scanner.ts +360 -0
  88. package/cli/src/scanners/index.ts +5 -0
  89. package/cli/src/types/scan.ts +84 -0
  90. package/cli/src/utils/config.ts +145 -0
  91. package/cli/tsconfig.bundle.json +12 -0
  92. package/cli/tsconfig.json +23 -0
  93. package/cli/vitest.config.ts +57 -0
  94. package/core/LICENSE +24 -0
  95. package/core/README.md +64 -0
  96. package/core/package.json +81 -0
  97. package/core/src/__tests__/adapters-contract/adapters-contract.test.md +156 -0
  98. package/core/src/__tests__/index.test.ts +31 -0
  99. package/core/src/__tests__/integration/phase3.test.ts +405 -0
  100. package/core/src/__tests__/pack/validator.test.ts +312 -0
  101. package/core/src/__tests__/secrets/crypto.test.ts +190 -0
  102. package/core/src/__tests__/secrets/manager.test.ts +316 -0
  103. package/core/src/__tests__/security/redactor-phase3.test.ts +233 -0
  104. package/core/src/__tests__/serve/health-checker.test.ts +155 -0
  105. package/core/src/__tests__/serve/process-manager.test.ts +213 -0
  106. package/core/src/__tests__/serve/server.test.ts +103 -0
  107. package/core/src/__tests__/vault/cas.test.ts +178 -0
  108. package/core/src/__tests__/vault/vault.test.ts +296 -0
  109. package/core/src/adapters/__tests__/gitleaks-secrets.test.ts +452 -0
  110. package/core/src/adapters/__tests__/k6-perf.test.ts +538 -0
  111. package/core/src/adapters/__tests__/osv-deps.test.ts +471 -0
  112. package/core/src/adapters/__tests__/playwright-native-api.test.ts +792 -0
  113. package/core/src/adapters/__tests__/playwright-ui-e2e.test.ts +431 -0
  114. package/core/src/adapters/__tests__/playwright-ui.test.ts +1073 -0
  115. package/core/src/adapters/__tests__/semgrep-sast.test.ts +436 -0
  116. package/core/src/adapters/__tests__/zap-dast.test.ts +453 -0
  117. package/core/src/adapters/gitleaks-secrets.ts +521 -0
  118. package/core/src/adapters/k6-perf.ts +479 -0
  119. package/core/src/adapters/osv-deps.ts +467 -0
  120. package/core/src/adapters/playwright-native-adapter.ts +472 -0
  121. package/core/src/adapters/playwright-native-api.ts +619 -0
  122. package/core/src/adapters/playwright-ui.ts +1088 -0
  123. package/core/src/adapters/semgrep-sast.ts +410 -0
  124. package/core/src/adapters/zap-dast.ts +551 -0
  125. package/core/src/ai/__tests__/deepseek-provider.test.ts +586 -0
  126. package/core/src/ai/__tests__/ollama-provider.test.ts +641 -0
  127. package/core/src/ai/anthropic-provider.ts +248 -0
  128. package/core/src/ai/deepseek-provider.ts +301 -0
  129. package/core/src/ai/index.ts +87 -0
  130. package/core/src/ai/llm-client.ts +52 -0
  131. package/core/src/ai/mock-provider.ts +146 -0
  132. package/core/src/ai/ollama-provider.ts +255 -0
  133. package/core/src/ai/openai-provider.ts +226 -0
  134. package/core/src/ai/provider-factory.ts +408 -0
  135. package/core/src/artifacts/README.md +78 -0
  136. package/core/src/artifacts/index.ts +16 -0
  137. package/core/src/artifacts/ui-artifacts.ts +412 -0
  138. package/core/src/assertions/__tests__/engine.test.ts +360 -0
  139. package/core/src/assertions/engine.ts +577 -0
  140. package/core/src/assertions/index.ts +13 -0
  141. package/core/src/assertions/types.ts +229 -0
  142. package/core/src/auth/__tests__/api-key-provider.test.ts +282 -0
  143. package/core/src/auth/__tests__/auth-manager.test.ts +430 -0
  144. package/core/src/auth/__tests__/basic-auth-provider.test.ts +364 -0
  145. package/core/src/auth/__tests__/cloud-providers.test.ts +751 -0
  146. package/core/src/auth/__tests__/jwt-provider.test.ts +400 -0
  147. package/core/src/auth/__tests__/oauth2-provider.test.ts +383 -0
  148. package/core/src/auth/__tests__/totp-provider.test.ts +294 -0
  149. package/core/src/auth/__tests__/ui-login-provider.test.ts +323 -0
  150. package/core/src/auth/api-key-provider.ts +75 -0
  151. package/core/src/auth/aws-iam-provider.ts +212 -0
  152. package/core/src/auth/azure-ad-provider.ts +126 -0
  153. package/core/src/auth/basic-auth-provider.ts +133 -0
  154. package/core/src/auth/gcp-adc-provider.ts +146 -0
  155. package/core/src/auth/index.ts +342 -0
  156. package/core/src/auth/jwt-provider.ts +193 -0
  157. package/core/src/auth/manager.ts +281 -0
  158. package/core/src/auth/oauth2-provider.ts +141 -0
  159. package/core/src/auth/totp-provider.ts +163 -0
  160. package/core/src/auth/ui-login-provider.ts +242 -0
  161. package/core/src/cache/__tests__/lru-cache.test.ts +564 -0
  162. package/core/src/cache/index.ts +13 -0
  163. package/core/src/cache/lru-cache.ts +536 -0
  164. package/core/src/crawler/__tests__/journey-generator.test.ts +344 -0
  165. package/core/src/crawler/__tests__/selector-generator.test.ts +211 -0
  166. package/core/src/crawler/index.ts +335 -0
  167. package/core/src/crawler/journey-generator.ts +471 -0
  168. package/core/src/crawler/page-analyzer.ts +857 -0
  169. package/core/src/crawler/selector-generator.ts +280 -0
  170. package/core/src/crawler/types.ts +475 -0
  171. package/core/src/dashboard/__tests__/real-world.test.ts +430 -0
  172. package/core/src/dashboard/__tests__/server.test.ts +283 -0
  173. package/core/src/dashboard/__tests__/types.test.ts +208 -0
  174. package/core/src/dashboard/assets.ts +692 -0
  175. package/core/src/dashboard/index.ts +17 -0
  176. package/core/src/dashboard/server.ts +401 -0
  177. package/core/src/dashboard/types.ts +78 -0
  178. package/core/src/discoverer/__tests__/test-discoverer.test.ts +444 -0
  179. package/core/src/discoverer/index.ts +374 -0
  180. package/core/src/flakiness/__tests__/flakiness.test.ts +554 -0
  181. package/core/src/flakiness/index.ts +536 -0
  182. package/core/src/generation/__tests__/code-formatter.test.ts +170 -0
  183. package/core/src/generation/__tests__/code-generator-contract.test.ts +207 -0
  184. package/core/src/generation/__tests__/code-generator.test.ts +586 -0
  185. package/core/src/generation/__tests__/crawler-pack-generator.test.ts +479 -0
  186. package/core/src/generation/__tests__/generation-e2e-b2bshop.test.ts +718 -0
  187. package/core/src/generation/__tests__/generation-integration.test.ts +655 -0
  188. package/core/src/generation/__tests__/pack-generator.test.ts +408 -0
  189. package/core/src/generation/__tests__/prompt-builder.test.ts +200 -0
  190. package/core/src/generation/__tests__/real-provider-integration.test.ts +414 -0
  191. package/core/src/generation/__tests__/source-analyzer.test.ts +774 -0
  192. package/core/src/generation/__tests__/test-optimizer.test.ts +255 -0
  193. package/core/src/generation/code-formatter.ts +408 -0
  194. package/core/src/generation/code-generator.ts +470 -0
  195. package/core/src/generation/crawler-pack-generator.ts +289 -0
  196. package/core/src/generation/generator.ts +113 -0
  197. package/core/src/generation/index.ts +59 -0
  198. package/core/src/generation/pack-generator.ts +527 -0
  199. package/core/src/generation/prompt-builder.ts +772 -0
  200. package/core/src/generation/source-analyzer.ts +830 -0
  201. package/core/src/generation/test-optimizer.ts +474 -0
  202. package/core/src/generation/types.ts +217 -0
  203. package/core/src/hooks/__tests__/compose.test.ts +636 -0
  204. package/core/src/hooks/__tests__/runner.test.ts +478 -0
  205. package/core/src/hooks/compose.ts +268 -0
  206. package/core/src/hooks/runner.ts +364 -0
  207. package/core/src/index.ts +237 -0
  208. package/core/src/pack/__tests__/migrator.test.ts +594 -0
  209. package/core/src/pack/__tests__/validator.test.ts +759 -0
  210. package/core/src/pack/migrator.ts +353 -0
  211. package/core/src/pack/validator.ts +359 -0
  212. package/core/src/pack-v2/__tests__/loader.test.ts +533 -0
  213. package/core/src/pack-v2/__tests__/migrator.test.ts +455 -0
  214. package/core/src/pack-v2/__tests__/validator.test.ts +549 -0
  215. package/core/src/pack-v2/index.ts +41 -0
  216. package/core/src/pack-v2/loader.ts +321 -0
  217. package/core/src/pack-v2/migrator.ts +540 -0
  218. package/core/src/pack-v2/validator.ts +673 -0
  219. package/core/src/parallel/README.md +143 -0
  220. package/core/src/parallel/index.ts +16 -0
  221. package/core/src/parallel/parallel-runner.ts +282 -0
  222. package/core/src/proof/__tests__/proof-roundtrip.test.ts +149 -0
  223. package/core/src/proof/__tests__/schema-validation-manual.mjs +211 -0
  224. package/core/src/proof/__tests__/schema-validation.test.ts +336 -0
  225. package/core/src/proof/__tests__/signer.test.ts +486 -0
  226. package/core/src/proof/__tests__/temporal-regression.test.ts +537 -0
  227. package/core/src/proof/__tests__/verifier-advanced.test.ts +588 -0
  228. package/core/src/proof/__tests__/verifier.test.ts +413 -0
  229. package/core/src/proof/bundle.ts +290 -0
  230. package/core/src/proof/canonicalize.ts +116 -0
  231. package/core/src/proof/index.ts +74 -0
  232. package/core/src/proof/schema.ts +285 -0
  233. package/core/src/proof/signer.ts +293 -0
  234. package/core/src/proof/verifier.ts +380 -0
  235. package/core/src/regression/__tests__/detector.test.ts +396 -0
  236. package/core/src/regression/__tests__/trend-analyzer.test.ts +300 -0
  237. package/core/src/regression/detector.ts +629 -0
  238. package/core/src/regression/index.ts +34 -0
  239. package/core/src/regression/trend-analyzer.ts +468 -0
  240. package/core/src/regression/types.ts +295 -0
  241. package/core/src/regression/vault.ts +419 -0
  242. package/core/src/repair/__tests__/repairer.test.ts +572 -0
  243. package/core/src/repair/__tests__/types.test.ts +302 -0
  244. package/core/src/repair/engine/__tests__/fixer.test.ts +482 -0
  245. package/core/src/repair/engine/__tests__/suggestion-engine.test.ts +395 -0
  246. package/core/src/repair/engine/fixer.ts +271 -0
  247. package/core/src/repair/engine/suggestion-engine.ts +234 -0
  248. package/core/src/repair/index.ts +53 -0
  249. package/core/src/repair/repairer.ts +376 -0
  250. package/core/src/repair/types.ts +119 -0
  251. package/core/src/repair/utils/__tests__/error-analyzer.test.ts +454 -0
  252. package/core/src/repair/utils/error-analyzer.ts +308 -0
  253. package/core/src/reporting/README.md +144 -0
  254. package/core/src/reporting/html-reporter.ts +835 -0
  255. package/core/src/reporting/index.ts +16 -0
  256. package/core/src/retry/README.md +192 -0
  257. package/core/src/retry/__tests__/flakiness-integration.test.ts +475 -0
  258. package/core/src/retry/__tests__/retry-engine.test.ts +424 -0
  259. package/core/src/retry/flakiness-integration.ts +267 -0
  260. package/core/src/retry/index.ts +48 -0
  261. package/core/src/retry/retry-engine.ts +368 -0
  262. package/core/src/retry/types.ts +208 -0
  263. package/core/src/retry/vault.ts +413 -0
  264. package/core/src/runner/__tests__/flakiness-integration.test.ts +566 -0
  265. package/core/src/runner/__tests__/phase3-e2e-b2bshop.test.ts +218 -0
  266. package/core/src/runner/__tests__/phase3-e2e-reqres.test.ts +199 -0
  267. package/core/src/runner/__tests__/phase3-runner.test.ts +1118 -0
  268. package/core/src/runner/e2e-helpers.ts +216 -0
  269. package/core/src/runner/phase3-runner.ts +1236 -0
  270. package/core/src/schemas/gherkin-report.json +122 -0
  271. package/core/src/secrets/__tests__/crypto.test.ts +180 -0
  272. package/core/src/secrets/crypto.ts +289 -0
  273. package/core/src/secrets/manager.ts +272 -0
  274. package/core/src/security/__tests__/hardening.test.ts +480 -0
  275. package/core/src/security/redaction-patterns-extended.ts +278 -0
  276. package/core/src/security/redactor.ts +326 -0
  277. package/core/src/self-healing/assertion-healer.ts +485 -0
  278. package/core/src/self-healing/engine.ts +626 -0
  279. package/core/src/self-healing/index.ts +33 -0
  280. package/core/src/self-healing/selector-healer.ts +488 -0
  281. package/core/src/self-healing/types.ts +193 -0
  282. package/core/src/serve/diagnostics-collector.ts +201 -0
  283. package/core/src/serve/health-checker.ts +274 -0
  284. package/core/src/serve/index.ts +9 -0
  285. package/core/src/serve/metrics-collector.ts +386 -0
  286. package/core/src/serve/process-manager.ts +265 -0
  287. package/core/src/serve/server.ts +230 -0
  288. package/core/src/slo/config.ts +408 -0
  289. package/core/src/slo/index.ts +68 -0
  290. package/core/src/slo/sli-calculator.ts +474 -0
  291. package/core/src/slo/slo-tracker.ts +481 -0
  292. package/core/src/slo/types.ts +408 -0
  293. package/core/src/slo/vault.ts +600 -0
  294. package/core/src/tui/__tests__/monitor.test.ts +336 -0
  295. package/core/src/tui/__tests__/real-world.test.ts +376 -0
  296. package/core/src/tui/__tests__/renderer.test.ts +201 -0
  297. package/core/src/tui/__tests__/types.test.ts +295 -0
  298. package/core/src/tui/index.ts +19 -0
  299. package/core/src/tui/monitor.ts +331 -0
  300. package/core/src/tui/renderer.ts +269 -0
  301. package/core/src/tui/types.ts +68 -0
  302. package/core/src/types/pack-v1.ts +305 -0
  303. package/core/src/types/pack-v2.ts +491 -0
  304. package/core/src/types/trust-score.ts +258 -0
  305. package/core/src/vault/__tests__/flakiness-vault.test.ts +562 -0
  306. package/core/src/vault/__tests__/vault.test.ts +259 -0
  307. package/core/src/vault/cas.ts +323 -0
  308. package/core/src/vault/index.ts +1361 -0
  309. package/core/src/vault/schema.sql +168 -0
  310. package/core/src/visual/README.md +185 -0
  311. package/core/src/visual/index.ts +14 -0
  312. package/core/src/visual/visual-regression.ts +347 -0
  313. package/core/src/watch/__tests__/watch-mode.test.ts +192 -0
  314. package/core/src/watch/index.ts +14 -0
  315. package/core/src/watch/watch-mode.ts +565 -0
  316. package/core/tsconfig.json +12 -0
  317. package/core/vitest.config.ts +52 -0
  318. package/docs/ARCHITECTURE.md +901 -0
  319. package/docs/AUDIT-GLOBAL-DEC2025.md +271 -0
  320. package/docs/BETA_TESTING.md +257 -0
  321. package/docs/BETA_TESTING_PLAN.md +727 -0
  322. package/docs/CERTIFICATION-REPORT.md +142 -0
  323. package/docs/COMPLETE_AUDIT_REFACTORING.md +965 -0
  324. package/docs/DEVELOPMENT.md +331 -0
  325. package/docs/DEVELOPMENT_HISTORY.md +345 -0
  326. package/docs/LIMITATIONS.md +176 -0
  327. package/docs/MIGRATION.md +303 -0
  328. package/docs/OPTION_3_4_EXPLORATION.md +1257 -0
  329. package/docs/PHASE1_PERFORMANCE.md +144 -0
  330. package/docs/QA360_Cloud.postman_collection.json +89 -0
  331. package/docs/README.md +50 -0
  332. package/docs/STATUS.md +179 -0
  333. package/docs/STRATEGIC_STUDY_GOOSE_INTEGRATION.md +615 -0
  334. package/docs/USER_GUIDE.md +687 -0
  335. package/docs/WORK-DONE-ADAPTER-TESTS.md +136 -0
  336. package/docs/adapters-security.md +485 -0
  337. package/docs/architecture-diagram.mmd +168 -0
  338. package/docs/archive/ARCH-01-DAY6-BUILD-FIXES.md +396 -0
  339. package/docs/archive/ARCH-01-DAY6-FINAL-STATUS.md +324 -0
  340. package/docs/archive/ARCH-01_MCP_MERGE_ANALYSIS.md +644 -0
  341. package/docs/archive/ARCH-01_NEXT_STEPS.md +60 -0
  342. package/docs/archive/BRANCH_PROTECTION.md +183 -0
  343. package/docs/archive/CI_LOCKDOWN_CHECKLIST.md +222 -0
  344. package/docs/archive/HANDOFF_TEST-01.md +669 -0
  345. package/docs/archive/LEGAL_READY_PLACEHOLDERS.md +372 -0
  346. package/docs/archive/NODE_UPGRADE_GUIDE.md +188 -0
  347. package/docs/archive/PHASE1_COMPLETION.md +386 -0
  348. package/docs/archive/PHASE2_COMPLETION.md +404 -0
  349. package/docs/archive/PHASE3_AND_4_FINAL.md +360 -0
  350. package/docs/archive/PHASE3_COMPLETE.md +301 -0
  351. package/docs/archive/PHASE3_STATUS.md +255 -0
  352. package/docs/archive/PRE-WEEK2-AUDIT.md +364 -0
  353. package/docs/archive/README.md +33 -0
  354. package/docs/archive/SCHEMA_AJV_2020_FIX.md +245 -0
  355. package/docs/archive/TEST-01_AUDIT_REPORT.md +240 -0
  356. package/docs/archive/TEST-01_COVERAGE_PLAN.md +423 -0
  357. package/docs/budgets-advanced.md +308 -0
  358. package/docs/examples/history-export-gc.md +285 -0
  359. package/docs/examples/pack-v2-complete.yaml +158 -0
  360. package/docs/examples/pack-v2-quickstart.yaml +24 -0
  361. package/docs/examples/pack-v2-ui-login.yaml +81 -0
  362. package/docs/examples/qa360-report.json +50 -0
  363. package/docs/history.md +565 -0
  364. package/docs/hooks.md +304 -0
  365. package/docs/llm-providers.md +419 -0
  366. package/docs/mcp-server.md +651 -0
  367. package/docs/mcp-tools.md +1131 -0
  368. package/docs/pack-v1.md +383 -0
  369. package/docs/pack-v2.md +558 -0
  370. package/docs/proofs.md +670 -0
  371. package/docs/quickstart-5min.md +257 -0
  372. package/docs/readiness-ci.md +654 -0
  373. package/docs/rfc/README.md +20 -0
  374. package/docs/rfc/proof-bundle-v1.md +787 -0
  375. package/docs/secrets.md +392 -0
  376. package/docs/serve.md +494 -0
  377. package/docs/vault.md +491 -0
  378. package/e2e/qa360-e2e.test.ts +696 -0
  379. package/e2e/vitest.config.ts +18 -0
  380. package/examples/README.md +30 -140
  381. package/examples/ci/docker-compose-serve.yml +375 -0
  382. package/examples/ci/github-actions-serve.yml +345 -0
  383. package/examples/ci/gitlab-ci-serve.yml +407 -0
  384. package/examples/datasets/README.md +101 -0
  385. package/examples/datasets/b2bshop.ts +155 -0
  386. package/examples/datasets/index.ts +57 -0
  387. package/examples/datasets/reqres.ts +195 -0
  388. package/examples/future-api/README.md +16 -0
  389. package/examples/future-api/diag.js +7 -0
  390. package/examples/future-api/health.js +4 -0
  391. package/examples/future-api/packs.js +13 -0
  392. package/examples/future-api/runpack.js +10 -0
  393. package/examples/generation/README.md +148 -0
  394. package/examples/generation/pack-generator-example.js +115 -0
  395. package/examples/generation/source-analyzer-example.js +115 -0
  396. package/examples/httpbin/pack.yml +59 -0
  397. package/examples/load-testing/mcp-load.yml +115 -0
  398. package/examples/load-testing/mcp-stdio.yml +95 -0
  399. package/examples/mcp/claude-desktop-config.json +33 -0
  400. package/examples/mcp/claude-desktop.json +16 -0
  401. package/examples/mcp/conversation-sample.md +131 -0
  402. package/examples/mcp/demo-60s.md +330 -0
  403. package/examples/mcp/sample-conversation.jsonl +21 -0
  404. package/examples/mcp/vscode-settings.json +22 -0
  405. package/examples/pack-v2-complete.yml +242 -0
  406. package/examples/pack-v2-examples.md +244 -0
  407. package/examples/pack-v2-quickstart.yml +55 -0
  408. package/examples/packs-business/ecommerce-api.yml +121 -0
  409. package/examples/packs-business/saas-dashboard-ui.yml +133 -0
  410. package/examples/packs-conformance/compose-multi.yml +174 -0
  411. package/examples/packs-conformance/full.yml +152 -0
  412. package/examples/packs-conformance/heavy-artifacts.yml +152 -0
  413. package/examples/packs-conformance/minimal.yml +71 -0
  414. package/examples/packs-conformance/secrets-missing.yml +97 -0
  415. package/examples/packs-conformance/timeouts.yml +77 -0
  416. package/examples/proofs/e2e-playwright-proof.json +75 -0
  417. package/examples/proofs/httpbin-proof.json +69 -0
  418. package/examples/proofs/multi-adapter-proof.json +117 -0
  419. package/examples/proofs/test-proof.json +26 -0
  420. package/examples/restful-api-dev/README.md +102 -0
  421. package/examples/restful-api-dev/restful-api-advanced.yml +29 -0
  422. package/examples/restful-api-dev/restful-api-basic.yml +29 -0
  423. package/examples/web-lite/.github/workflows/qa360-phase3.yml +73 -0
  424. package/examples/web-lite/api-mock/server.js +258 -0
  425. package/examples/web-lite/pack.yml +71 -0
  426. package/examples/web-lite/services.yml +43 -0
  427. package/examples/web-lite/web-content/healthz +1 -0
  428. package/examples/web-lite/web-content/index.html +259 -0
  429. package/package.json +55 -45
  430. package/packages/mcp/CHANGELOG.md +109 -0
  431. package/packages/mcp/IMPLEMENTATION_SUMMARY.md +350 -0
  432. package/packages/mcp/LICENSE +21 -0
  433. package/packages/mcp/QUICK_START.md +291 -0
  434. package/packages/mcp/README.md +294 -0
  435. package/packages/mcp/TELEMETRY.md +220 -0
  436. package/packages/mcp/package.json +92 -0
  437. package/packages/mcp/scripts/generate-sbom-fallback.cjs +84 -0
  438. package/packages/mcp/scripts/safe-postinstall.cjs +32 -0
  439. package/packages/mcp/src/__tests__/contract.test.ts +902 -0
  440. package/packages/mcp/src/cli/cli.ts +137 -0
  441. package/packages/mcp/src/cli/doctor.ts +286 -0
  442. package/packages/mcp/src/cli/fix.ts +99 -0
  443. package/packages/mcp/src/cli/init.ts +233 -0
  444. package/packages/mcp/src/cli/postinstall.ts +14 -0
  445. package/packages/mcp/src/cli/reset.ts +44 -0
  446. package/packages/mcp/src/cli/telemetry.ts +166 -0
  447. package/packages/mcp/src/cli/test-dx.ts +94 -0
  448. package/packages/mcp/src/cli/uninstall.ts +80 -0
  449. package/packages/mcp/src/cli/up.ts +178 -0
  450. package/packages/mcp/src/index.ts +12 -0
  451. package/packages/mcp/src/scripts/e2e-local.ts +337 -0
  452. package/packages/mcp/src/scripts/verify-settings.ts +242 -0
  453. package/packages/mcp/src/security/audit.ts +244 -0
  454. package/packages/mcp/src/security/manager.ts +242 -0
  455. package/packages/mcp/src/server/full-server.ts +212 -0
  456. package/packages/mcp/src/server/minimal-server.ts +134 -0
  457. package/packages/mcp/src/tools/history.ts +388 -0
  458. package/packages/mcp/src/tools/pack.ts +449 -0
  459. package/packages/mcp/src/tools/registry.ts +638 -0
  460. package/packages/mcp/src/tools/report.ts +100 -0
  461. package/packages/mcp/src/tools/run.ts +268 -0
  462. package/packages/mcp/src/tools/secrets.ts +198 -0
  463. package/packages/mcp/src/tools/serve.ts +221 -0
  464. package/packages/mcp/src/tools/triage.ts +532 -0
  465. package/packages/mcp/src/tools/types.ts +26 -0
  466. package/packages/mcp/src/tools/vault.ts +164 -0
  467. package/packages/mcp/src/tools/verify.ts +166 -0
  468. package/packages/mcp/src/types/index.ts +311 -0
  469. package/packages/mcp/src/types/mcp-stubs.ts +83 -0
  470. package/packages/mcp/tsconfig.json +16 -0
  471. package/playwright.config.ts +20 -0
  472. package/pnpm-workspace.yaml +4 -0
  473. package/run-test-and-push.sh +20 -0
  474. package/scripts/build-proof-cli.sh +110 -0
  475. package/scripts/ci/check-windows-paths.js +92 -0
  476. package/scripts/ci/invariants.sh +124 -0
  477. package/scripts/ci/make-final-bundle.js +106 -0
  478. package/scripts/ci/mcp-run-multipack.js +305 -0
  479. package/scripts/ci/run-pack-suite.sh +103 -0
  480. package/scripts/ci/run-phase7-final.sh +190 -0
  481. package/scripts/ci/slo-assert.js +158 -0
  482. package/scripts/ci/test-fault-tolerance.sh +301 -0
  483. package/scripts/install-mcp.sh +66 -0
  484. package/scripts/mcp-smoke.mjs +27 -0
  485. package/scripts/smoke.sh +26 -0
  486. package/scripts/stress-test.js +288 -0
  487. package/scripts/validate-examples.mjs +404 -0
  488. package/scripts/validation/simple-pack-check.sh +51 -0
  489. package/scripts/validation/validate-universal-pack.mjs +77 -0
  490. package/scripts/verify-persistence.js +127 -0
  491. package/test-pack.yaml +43 -0
  492. package/test-results/.last-run.json +4 -0
  493. package/test-runner.mjs +87 -0
  494. package/tests/artifacts.spec.js +147 -0
  495. package/tests/contracts.spec.js +239 -0
  496. package/tests/e2e/assertions.test.mjs +370 -0
  497. package/tests/e2e/crawler.test.mjs +451 -0
  498. package/tests/e2e/playwright-plus-plus.test.mjs +604 -0
  499. package/tests/e2e/proof-bundle.test.mjs +258 -0
  500. package/tests/e2e/real-world/saucedemo.test.mjs +714 -0
  501. package/tests/e2e/real-world/the-internet-herokuapp.test.mjs +760 -0
  502. package/tests/e2e/ui-actions.test.mjs +546 -0
  503. package/tests/gherkin.e2e.spec.ts +310 -0
  504. package/tests/no-console-errors.spec.js +136 -0
  505. package/tests/pdf.spec.ts +252 -0
  506. package/tests/run-pack.spec.ts +58 -0
  507. package/tsconfig.base.json +15 -0
  508. package/tsconfig.build.json +8 -0
  509. package/tsconfig.json +37 -0
  510. package/tsconfig.test.json +18 -0
  511. package/typedoc.json +37 -0
  512. package/ui/README.md +51 -0
  513. package/verify-proof.mjs +60 -0
  514. package/dist/cli-minimal.d.ts +0 -6
  515. package/dist/cli-minimal.js +0 -36
  516. package/dist/commands/ai.d.ts +0 -41
  517. package/dist/commands/ai.js +0 -511
  518. package/dist/commands/ask.d.ts +0 -94
  519. package/dist/commands/ask.js +0 -582
  520. package/dist/commands/coverage.d.ts +0 -8
  521. package/dist/commands/coverage.js +0 -252
  522. package/dist/commands/crawl.d.ts +0 -24
  523. package/dist/commands/crawl.js +0 -121
  524. package/dist/commands/doctor.d.ts +0 -54
  525. package/dist/commands/doctor.js +0 -513
  526. package/dist/commands/examples.d.ts +0 -33
  527. package/dist/commands/examples.js +0 -193
  528. package/dist/commands/explain.d.ts +0 -27
  529. package/dist/commands/explain.js +0 -630
  530. package/dist/commands/flakiness.d.ts +0 -73
  531. package/dist/commands/flakiness.js +0 -435
  532. package/dist/commands/generate.d.ts +0 -66
  533. package/dist/commands/generate.js +0 -438
  534. package/dist/commands/history.d.ts +0 -76
  535. package/dist/commands/history.js +0 -757
  536. package/dist/commands/init.d.ts +0 -106
  537. package/dist/commands/init.js +0 -599
  538. package/dist/commands/monitor.d.ts +0 -27
  539. package/dist/commands/monitor.js +0 -225
  540. package/dist/commands/ollama.d.ts +0 -40
  541. package/dist/commands/ollama.js +0 -301
  542. package/dist/commands/pack.d.ts +0 -70
  543. package/dist/commands/pack.js +0 -413
  544. package/dist/commands/regression.d.ts +0 -8
  545. package/dist/commands/regression.js +0 -340
  546. package/dist/commands/repair.d.ts +0 -26
  547. package/dist/commands/repair.js +0 -307
  548. package/dist/commands/report.d.ts +0 -62
  549. package/dist/commands/report.js +0 -378
  550. package/dist/commands/retry.d.ts +0 -43
  551. package/dist/commands/retry.js +0 -275
  552. package/dist/commands/run.d.ts +0 -41
  553. package/dist/commands/run.js +0 -169
  554. package/dist/commands/scan.d.ts +0 -5
  555. package/dist/commands/scan.js +0 -155
  556. package/dist/commands/secrets.d.ts +0 -58
  557. package/dist/commands/secrets.js +0 -289
  558. package/dist/commands/serve.d.ts +0 -13
  559. package/dist/commands/serve.js +0 -156
  560. package/dist/commands/slo.d.ts +0 -8
  561. package/dist/commands/slo.js +0 -327
  562. package/dist/commands/verify.d.ts +0 -32
  563. package/dist/commands/verify.js +0 -278
  564. package/dist/core/adapters/gitleaks-secrets.d.ts +0 -114
  565. package/dist/core/adapters/gitleaks-secrets.js +0 -410
  566. package/dist/core/adapters/k6-perf.d.ts +0 -85
  567. package/dist/core/adapters/k6-perf.js +0 -398
  568. package/dist/core/adapters/osv-deps.d.ts +0 -123
  569. package/dist/core/adapters/osv-deps.js +0 -372
  570. package/dist/core/adapters/playwright-native-adapter.d.ts +0 -121
  571. package/dist/core/adapters/playwright-native-adapter.js +0 -339
  572. package/dist/core/adapters/playwright-native-api.d.ts +0 -183
  573. package/dist/core/adapters/playwright-native-api.js +0 -461
  574. package/dist/core/adapters/playwright-ui.d.ts +0 -197
  575. package/dist/core/adapters/playwright-ui.js +0 -840
  576. package/dist/core/adapters/semgrep-sast.d.ts +0 -99
  577. package/dist/core/adapters/semgrep-sast.js +0 -322
  578. package/dist/core/adapters/zap-dast.d.ts +0 -133
  579. package/dist/core/adapters/zap-dast.js +0 -424
  580. package/dist/core/ai/anthropic-provider.d.ts +0 -50
  581. package/dist/core/ai/anthropic-provider.js +0 -211
  582. package/dist/core/ai/deepseek-provider.d.ts +0 -81
  583. package/dist/core/ai/deepseek-provider.js +0 -254
  584. package/dist/core/ai/index.d.ts +0 -60
  585. package/dist/core/ai/index.js +0 -18
  586. package/dist/core/ai/llm-client.d.ts +0 -45
  587. package/dist/core/ai/llm-client.js +0 -7
  588. package/dist/core/ai/mock-provider.d.ts +0 -49
  589. package/dist/core/ai/mock-provider.js +0 -121
  590. package/dist/core/ai/ollama-provider.d.ts +0 -78
  591. package/dist/core/ai/ollama-provider.js +0 -192
  592. package/dist/core/ai/openai-provider.d.ts +0 -48
  593. package/dist/core/ai/openai-provider.js +0 -188
  594. package/dist/core/ai/provider-factory.d.ts +0 -160
  595. package/dist/core/ai/provider-factory.js +0 -269
  596. package/dist/core/artifacts/index.d.ts +0 -6
  597. package/dist/core/artifacts/index.js +0 -6
  598. package/dist/core/artifacts/ui-artifacts.d.ts +0 -133
  599. package/dist/core/artifacts/ui-artifacts.js +0 -304
  600. package/dist/core/assertions/engine.d.ts +0 -51
  601. package/dist/core/assertions/engine.js +0 -530
  602. package/dist/core/assertions/index.d.ts +0 -11
  603. package/dist/core/assertions/index.js +0 -11
  604. package/dist/core/assertions/types.d.ts +0 -121
  605. package/dist/core/assertions/types.js +0 -37
  606. package/dist/core/auth/api-key-provider.d.ts +0 -16
  607. package/dist/core/auth/api-key-provider.js +0 -63
  608. package/dist/core/auth/aws-iam-provider.d.ts +0 -35
  609. package/dist/core/auth/aws-iam-provider.js +0 -177
  610. package/dist/core/auth/azure-ad-provider.d.ts +0 -15
  611. package/dist/core/auth/azure-ad-provider.js +0 -99
  612. package/dist/core/auth/basic-auth-provider.d.ts +0 -26
  613. package/dist/core/auth/basic-auth-provider.js +0 -111
  614. package/dist/core/auth/gcp-adc-provider.d.ts +0 -27
  615. package/dist/core/auth/gcp-adc-provider.js +0 -126
  616. package/dist/core/auth/index.d.ts +0 -238
  617. package/dist/core/auth/index.js +0 -82
  618. package/dist/core/auth/jwt-provider.d.ts +0 -19
  619. package/dist/core/auth/jwt-provider.js +0 -160
  620. package/dist/core/auth/manager.d.ts +0 -84
  621. package/dist/core/auth/manager.js +0 -230
  622. package/dist/core/auth/oauth2-provider.d.ts +0 -17
  623. package/dist/core/auth/oauth2-provider.js +0 -114
  624. package/dist/core/auth/totp-provider.d.ts +0 -31
  625. package/dist/core/auth/totp-provider.js +0 -134
  626. package/dist/core/auth/ui-login-provider.d.ts +0 -26
  627. package/dist/core/auth/ui-login-provider.js +0 -198
  628. package/dist/core/cache/index.d.ts +0 -7
  629. package/dist/core/cache/index.js +0 -6
  630. package/dist/core/cache/lru-cache.d.ts +0 -203
  631. package/dist/core/cache/lru-cache.js +0 -397
  632. package/dist/core/core/coverage/analyzer.d.ts +0 -101
  633. package/dist/core/core/coverage/analyzer.js +0 -415
  634. package/dist/core/core/coverage/collector.d.ts +0 -74
  635. package/dist/core/core/coverage/collector.js +0 -459
  636. package/dist/core/core/coverage/config.d.ts +0 -37
  637. package/dist/core/core/coverage/config.js +0 -156
  638. package/dist/core/core/coverage/index.d.ts +0 -11
  639. package/dist/core/core/coverage/index.js +0 -15
  640. package/dist/core/core/coverage/types.d.ts +0 -267
  641. package/dist/core/core/coverage/types.js +0 -6
  642. package/dist/core/core/coverage/vault.d.ts +0 -95
  643. package/dist/core/core/coverage/vault.js +0 -405
  644. package/dist/core/coverage/analyzer.d.ts +0 -101
  645. package/dist/core/coverage/analyzer.js +0 -415
  646. package/dist/core/coverage/collector.d.ts +0 -74
  647. package/dist/core/coverage/collector.js +0 -459
  648. package/dist/core/coverage/config.d.ts +0 -37
  649. package/dist/core/coverage/config.js +0 -156
  650. package/dist/core/coverage/index.d.ts +0 -11
  651. package/dist/core/coverage/index.js +0 -15
  652. package/dist/core/coverage/types.d.ts +0 -267
  653. package/dist/core/coverage/types.js +0 -6
  654. package/dist/core/coverage/vault.d.ts +0 -95
  655. package/dist/core/coverage/vault.js +0 -405
  656. package/dist/core/crawler/index.d.ts +0 -57
  657. package/dist/core/crawler/index.js +0 -281
  658. package/dist/core/crawler/journey-generator.d.ts +0 -49
  659. package/dist/core/crawler/journey-generator.js +0 -412
  660. package/dist/core/crawler/page-analyzer.d.ts +0 -88
  661. package/dist/core/crawler/page-analyzer.js +0 -709
  662. package/dist/core/crawler/selector-generator.d.ts +0 -34
  663. package/dist/core/crawler/selector-generator.js +0 -240
  664. package/dist/core/crawler/types.d.ts +0 -353
  665. package/dist/core/crawler/types.js +0 -6
  666. package/dist/core/dashboard/assets.d.ts +0 -6
  667. package/dist/core/dashboard/assets.js +0 -690
  668. package/dist/core/dashboard/index.d.ts +0 -6
  669. package/dist/core/dashboard/index.js +0 -5
  670. package/dist/core/dashboard/server.d.ts +0 -72
  671. package/dist/core/dashboard/server.js +0 -354
  672. package/dist/core/dashboard/types.d.ts +0 -70
  673. package/dist/core/dashboard/types.js +0 -5
  674. package/dist/core/discoverer/index.d.ts +0 -115
  675. package/dist/core/discoverer/index.js +0 -250
  676. package/dist/core/flakiness/index.d.ts +0 -228
  677. package/dist/core/flakiness/index.js +0 -384
  678. package/dist/core/generation/code-formatter.d.ts +0 -111
  679. package/dist/core/generation/code-formatter.js +0 -307
  680. package/dist/core/generation/code-generator.d.ts +0 -144
  681. package/dist/core/generation/code-generator.js +0 -293
  682. package/dist/core/generation/crawler-pack-generator.d.ts +0 -44
  683. package/dist/core/generation/crawler-pack-generator.js +0 -231
  684. package/dist/core/generation/generator.d.ts +0 -40
  685. package/dist/core/generation/generator.js +0 -76
  686. package/dist/core/generation/index.d.ts +0 -32
  687. package/dist/core/generation/index.js +0 -30
  688. package/dist/core/generation/pack-generator.d.ts +0 -107
  689. package/dist/core/generation/pack-generator.js +0 -416
  690. package/dist/core/generation/prompt-builder.d.ts +0 -132
  691. package/dist/core/generation/prompt-builder.js +0 -672
  692. package/dist/core/generation/source-analyzer.d.ts +0 -213
  693. package/dist/core/generation/source-analyzer.js +0 -657
  694. package/dist/core/generation/test-optimizer.d.ts +0 -117
  695. package/dist/core/generation/test-optimizer.js +0 -328
  696. package/dist/core/generation/types.d.ts +0 -214
  697. package/dist/core/generation/types.js +0 -4
  698. package/dist/core/hooks/compose.d.ts +0 -61
  699. package/dist/core/hooks/compose.js +0 -225
  700. package/dist/core/hooks/runner.d.ts +0 -68
  701. package/dist/core/hooks/runner.js +0 -303
  702. package/dist/core/index.d.ts +0 -104
  703. package/dist/core/index.js +0 -91
  704. package/dist/core/pack/migrator.d.ts +0 -51
  705. package/dist/core/pack/migrator.js +0 -304
  706. package/dist/core/pack/validator.d.ts +0 -42
  707. package/dist/core/pack/validator.js +0 -322
  708. package/dist/core/pack-v2/index.d.ts +0 -9
  709. package/dist/core/pack-v2/index.js +0 -8
  710. package/dist/core/pack-v2/loader.d.ts +0 -62
  711. package/dist/core/pack-v2/loader.js +0 -259
  712. package/dist/core/pack-v2/migrator.d.ts +0 -61
  713. package/dist/core/pack-v2/migrator.js +0 -480
  714. package/dist/core/pack-v2/validator.d.ts +0 -61
  715. package/dist/core/pack-v2/validator.js +0 -577
  716. package/dist/core/parallel/index.d.ts +0 -6
  717. package/dist/core/parallel/index.js +0 -6
  718. package/dist/core/parallel/parallel-runner.d.ts +0 -107
  719. package/dist/core/parallel/parallel-runner.js +0 -192
  720. package/dist/core/proof/bundle.d.ts +0 -137
  721. package/dist/core/proof/bundle.js +0 -160
  722. package/dist/core/proof/canonicalize.d.ts +0 -47
  723. package/dist/core/proof/canonicalize.js +0 -105
  724. package/dist/core/proof/index.d.ts +0 -13
  725. package/dist/core/proof/index.js +0 -18
  726. package/dist/core/proof/schema.d.ts +0 -217
  727. package/dist/core/proof/schema.js +0 -263
  728. package/dist/core/proof/signer.d.ts +0 -111
  729. package/dist/core/proof/signer.js +0 -226
  730. package/dist/core/proof/verifier.d.ts +0 -97
  731. package/dist/core/proof/verifier.js +0 -308
  732. package/dist/core/regression/detector.d.ts +0 -107
  733. package/dist/core/regression/detector.js +0 -497
  734. package/dist/core/regression/index.d.ts +0 -9
  735. package/dist/core/regression/index.js +0 -11
  736. package/dist/core/regression/trend-analyzer.d.ts +0 -102
  737. package/dist/core/regression/trend-analyzer.js +0 -345
  738. package/dist/core/regression/types.d.ts +0 -222
  739. package/dist/core/regression/types.js +0 -7
  740. package/dist/core/regression/vault.d.ts +0 -87
  741. package/dist/core/regression/vault.js +0 -289
  742. package/dist/core/repair/engine/fixer.d.ts +0 -24
  743. package/dist/core/repair/engine/fixer.js +0 -226
  744. package/dist/core/repair/engine/suggestion-engine.d.ts +0 -18
  745. package/dist/core/repair/engine/suggestion-engine.js +0 -187
  746. package/dist/core/repair/index.d.ts +0 -10
  747. package/dist/core/repair/index.js +0 -13
  748. package/dist/core/repair/repairer.d.ts +0 -90
  749. package/dist/core/repair/repairer.js +0 -284
  750. package/dist/core/repair/types.d.ts +0 -91
  751. package/dist/core/repair/types.js +0 -6
  752. package/dist/core/repair/utils/error-analyzer.d.ts +0 -28
  753. package/dist/core/repair/utils/error-analyzer.js +0 -264
  754. package/dist/core/reporting/html-reporter.d.ts +0 -119
  755. package/dist/core/reporting/html-reporter.js +0 -737
  756. package/dist/core/reporting/index.d.ts +0 -6
  757. package/dist/core/reporting/index.js +0 -6
  758. package/dist/core/retry/flakiness-integration.d.ts +0 -60
  759. package/dist/core/retry/flakiness-integration.js +0 -228
  760. package/dist/core/retry/index.d.ts +0 -14
  761. package/dist/core/retry/index.js +0 -16
  762. package/dist/core/retry/retry-engine.d.ts +0 -80
  763. package/dist/core/retry/retry-engine.js +0 -296
  764. package/dist/core/retry/types.d.ts +0 -178
  765. package/dist/core/retry/types.js +0 -52
  766. package/dist/core/retry/vault.d.ts +0 -77
  767. package/dist/core/retry/vault.js +0 -304
  768. package/dist/core/runner/e2e-helpers.d.ts +0 -102
  769. package/dist/core/runner/e2e-helpers.js +0 -153
  770. package/dist/core/runner/phase3-runner.d.ts +0 -200
  771. package/dist/core/runner/phase3-runner.js +0 -1039
  772. package/dist/core/secrets/crypto.d.ts +0 -75
  773. package/dist/core/secrets/crypto.js +0 -223
  774. package/dist/core/secrets/manager.d.ts +0 -76
  775. package/dist/core/secrets/manager.js +0 -219
  776. package/dist/core/security/redaction-patterns-extended.d.ts +0 -27
  777. package/dist/core/security/redaction-patterns-extended.js +0 -247
  778. package/dist/core/security/redactor.d.ts +0 -71
  779. package/dist/core/security/redactor.js +0 -279
  780. package/dist/core/self-healing/assertion-healer.d.ts +0 -97
  781. package/dist/core/self-healing/assertion-healer.js +0 -371
  782. package/dist/core/self-healing/engine.d.ts +0 -122
  783. package/dist/core/self-healing/engine.js +0 -538
  784. package/dist/core/self-healing/index.d.ts +0 -10
  785. package/dist/core/self-healing/index.js +0 -11
  786. package/dist/core/self-healing/selector-healer.d.ts +0 -103
  787. package/dist/core/self-healing/selector-healer.js +0 -372
  788. package/dist/core/self-healing/types.d.ts +0 -152
  789. package/dist/core/self-healing/types.js +0 -6
  790. package/dist/core/serve/diagnostics-collector.d.ts +0 -32
  791. package/dist/core/serve/diagnostics-collector.js +0 -149
  792. package/dist/core/serve/health-checker.d.ts +0 -44
  793. package/dist/core/serve/health-checker.js +0 -219
  794. package/dist/core/serve/index.d.ts +0 -8
  795. package/dist/core/serve/index.js +0 -8
  796. package/dist/core/serve/metrics-collector.d.ts +0 -24
  797. package/dist/core/serve/metrics-collector.js +0 -322
  798. package/dist/core/serve/process-manager.d.ts +0 -36
  799. package/dist/core/serve/process-manager.js +0 -213
  800. package/dist/core/serve/server.d.ts +0 -36
  801. package/dist/core/serve/server.js +0 -191
  802. package/dist/core/slo/config.d.ts +0 -107
  803. package/dist/core/slo/config.js +0 -360
  804. package/dist/core/slo/index.d.ts +0 -11
  805. package/dist/core/slo/index.js +0 -15
  806. package/dist/core/slo/sli-calculator.d.ts +0 -92
  807. package/dist/core/slo/sli-calculator.js +0 -364
  808. package/dist/core/slo/slo-tracker.d.ts +0 -148
  809. package/dist/core/slo/slo-tracker.js +0 -379
  810. package/dist/core/slo/types.d.ts +0 -281
  811. package/dist/core/slo/types.js +0 -7
  812. package/dist/core/slo/vault.d.ts +0 -102
  813. package/dist/core/slo/vault.js +0 -427
  814. package/dist/core/tui/index.d.ts +0 -7
  815. package/dist/core/tui/index.js +0 -6
  816. package/dist/core/tui/monitor.d.ts +0 -92
  817. package/dist/core/tui/monitor.js +0 -271
  818. package/dist/core/tui/renderer.d.ts +0 -33
  819. package/dist/core/tui/renderer.js +0 -218
  820. package/dist/core/tui/types.d.ts +0 -63
  821. package/dist/core/tui/types.js +0 -5
  822. package/dist/core/types/pack-v1.d.ts +0 -251
  823. package/dist/core/types/pack-v1.js +0 -5
  824. package/dist/core/types/pack-v2.d.ts +0 -425
  825. package/dist/core/types/pack-v2.js +0 -8
  826. package/dist/core/types/trust-score.d.ts +0 -69
  827. package/dist/core/types/trust-score.js +0 -191
  828. package/dist/core/vault/cas.d.ts +0 -90
  829. package/dist/core/vault/cas.js +0 -261
  830. package/dist/core/vault/index.d.ts +0 -326
  831. package/dist/core/vault/index.js +0 -1042
  832. package/dist/core/visual/index.d.ts +0 -6
  833. package/dist/core/visual/index.js +0 -6
  834. package/dist/core/visual/visual-regression.d.ts +0 -113
  835. package/dist/core/visual/visual-regression.js +0 -236
  836. package/dist/core/watch/index.d.ts +0 -7
  837. package/dist/core/watch/index.js +0 -6
  838. package/dist/core/watch/watch-mode.d.ts +0 -213
  839. package/dist/core/watch/watch-mode.js +0 -389
  840. package/dist/generators/index.d.ts +0 -5
  841. package/dist/generators/index.js +0 -5
  842. package/dist/generators/json-reporter.d.ts +0 -10
  843. package/dist/generators/json-reporter.js +0 -12
  844. package/dist/generators/test-generator.d.ts +0 -18
  845. package/dist/generators/test-generator.js +0 -78
  846. package/dist/index.d.ts +0 -8
  847. package/dist/index.js +0 -246
  848. package/dist/scanners/dom-scanner.d.ts +0 -52
  849. package/dist/scanners/dom-scanner.js +0 -296
  850. package/dist/scanners/index.d.ts +0 -4
  851. package/dist/scanners/index.js +0 -4
  852. package/dist/schemas/pack.schema.json +0 -236
  853. package/dist/types/scan.d.ts +0 -68
  854. package/dist/types/scan.js +0 -4
  855. package/dist/utils/config.d.ts +0 -5
  856. package/dist/utils/config.js +0 -136
  857. /package/{bin → cli/bin}/qa360.js +0 -0
  858. /package/{examples → cli/examples}/accessibility.yml +0 -0
  859. /package/{examples → cli/examples}/api-basic.yml +0 -0
  860. /package/{examples → cli/examples}/complete.yml +0 -0
  861. /package/{examples → cli/examples}/crawler.yml +0 -0
  862. /package/{examples → cli/examples}/fullstack.yml +0 -0
  863. /package/{examples → cli/examples}/security.yml +0 -0
  864. /package/{examples → cli/examples}/ui-advanced.yml +0 -0
  865. /package/{examples → cli/examples}/ui-basic.yml +0 -0
  866. /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
+ }