playwright-intelligence-engine 0.0.0-stage → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +229 -3
  3. package/bin/pw-intel.js +37 -0
  4. package/dist/authoring/author.d.ts +83 -0
  5. package/dist/authoring/author.d.ts.map +1 -0
  6. package/dist/authoring/generation-contract.d.ts +90 -0
  7. package/dist/authoring/generation-contract.d.ts.map +1 -0
  8. package/dist/authoring/hybrid-author.d.ts +6 -0
  9. package/dist/authoring/hybrid-author.d.ts.map +1 -0
  10. package/dist/authoring/index.d.ts +7 -0
  11. package/dist/authoring/index.d.ts.map +1 -0
  12. package/dist/authoring/llm-author.d.ts +28 -0
  13. package/dist/authoring/llm-author.d.ts.map +1 -0
  14. package/dist/authoring/naming/index.d.ts +4 -0
  15. package/dist/authoring/naming/index.d.ts.map +1 -0
  16. package/dist/authoring/naming/name-plan.d.ts +45 -0
  17. package/dist/authoring/naming/name-plan.d.ts.map +1 -0
  18. package/dist/authoring/naming/name-planner.d.ts +25 -0
  19. package/dist/authoring/naming/name-planner.d.ts.map +1 -0
  20. package/dist/authoring/naming/naming-linter.d.ts +20 -0
  21. package/dist/authoring/naming/naming-linter.d.ts.map +1 -0
  22. package/dist/authoring/template-author.d.ts +6 -0
  23. package/dist/authoring/template-author.d.ts.map +1 -0
  24. package/dist/cli/index.d.ts +2 -0
  25. package/dist/cli/index.d.ts.map +1 -0
  26. package/dist/collectors/collector-interface.d.ts +7 -0
  27. package/dist/collectors/collector-interface.d.ts.map +1 -0
  28. package/dist/collectors/environment-collector.d.ts +12 -0
  29. package/dist/collectors/environment-collector.d.ts.map +1 -0
  30. package/dist/collectors/error-collector.d.ts +18 -0
  31. package/dist/collectors/error-collector.d.ts.map +1 -0
  32. package/dist/collectors/git-diff-collector.d.ts +20 -0
  33. package/dist/collectors/git-diff-collector.d.ts.map +1 -0
  34. package/dist/collectors/live-browser-collector.d.ts +45 -0
  35. package/dist/collectors/live-browser-collector.d.ts.map +1 -0
  36. package/dist/collectors/network-collector.d.ts +28 -0
  37. package/dist/collectors/network-collector.d.ts.map +1 -0
  38. package/dist/collectors/static-ast-collector.d.ts +32 -0
  39. package/dist/collectors/static-ast-collector.d.ts.map +1 -0
  40. package/dist/collectors/trace-collector.d.ts +12 -0
  41. package/dist/collectors/trace-collector.d.ts.map +1 -0
  42. package/dist/config/project-config.d.ts +33 -0
  43. package/dist/config/project-config.d.ts.map +1 -0
  44. package/dist/core/errors/engine-errors.d.ts +34 -0
  45. package/dist/core/errors/engine-errors.d.ts.map +1 -0
  46. package/dist/core/types/diagnostic-context.d.ts +151 -0
  47. package/dist/core/types/diagnostic-context.d.ts.map +1 -0
  48. package/dist/core/types/repair-evidence.d.ts +56 -0
  49. package/dist/core/types/repair-evidence.d.ts.map +1 -0
  50. package/dist/core/version.d.ts +13 -0
  51. package/dist/core/version.d.ts.map +1 -0
  52. package/dist/diagnostics/diagnostic-contract.d.ts +52 -0
  53. package/dist/diagnostics/diagnostic-contract.d.ts.map +1 -0
  54. package/dist/diagnostics/diagnostic-report.d.ts +11 -0
  55. package/dist/diagnostics/diagnostic-report.d.ts.map +1 -0
  56. package/dist/diagnostics/evidence-correlator.d.ts +22 -0
  57. package/dist/diagnostics/evidence-correlator.d.ts.map +1 -0
  58. package/dist/diagnostics/external-failure-evidence.d.ts +18 -0
  59. package/dist/diagnostics/external-failure-evidence.d.ts.map +1 -0
  60. package/dist/diagnostics/failure-category.d.ts +4 -0
  61. package/dist/diagnostics/failure-category.d.ts.map +1 -0
  62. package/dist/diagnostics/failure-classifier.d.ts +58 -0
  63. package/dist/diagnostics/failure-classifier.d.ts.map +1 -0
  64. package/dist/evaluation/evaluation-scorecard.d.ts +72 -0
  65. package/dist/evaluation/evaluation-scorecard.d.ts.map +1 -0
  66. package/dist/evaluation/repository-inspector.d.ts +21 -0
  67. package/dist/evaluation/repository-inspector.d.ts.map +1 -0
  68. package/dist/evaluation/repository-runner.d.ts +24 -0
  69. package/dist/evaluation/repository-runner.d.ts.map +1 -0
  70. package/dist/evidence/evidence-model.d.ts +88 -0
  71. package/dist/evidence/evidence-model.d.ts.map +1 -0
  72. package/dist/evidence/evidence-normalizer.d.ts +19 -0
  73. package/dist/evidence/evidence-normalizer.d.ts.map +1 -0
  74. package/dist/evidence/evidence-redactor.d.ts +37 -0
  75. package/dist/evidence/evidence-redactor.d.ts.map +1 -0
  76. package/dist/framework/config-adapter.d.ts +28 -0
  77. package/dist/framework/config-adapter.d.ts.map +1 -0
  78. package/dist/gate/index.d.ts +21 -0
  79. package/dist/gate/index.d.ts.map +1 -0
  80. package/dist/gate/oracle.d.ts +26 -0
  81. package/dist/gate/oracle.d.ts.map +1 -0
  82. package/dist/gate/quality.d.ts +27 -0
  83. package/dist/gate/quality.d.ts.map +1 -0
  84. package/dist/gate/safety.d.ts +28 -0
  85. package/dist/gate/safety.d.ts.map +1 -0
  86. package/dist/generator/architecture-generator.d.ts +55 -0
  87. package/dist/generator/architecture-generator.d.ts.map +1 -0
  88. package/dist/generator/assertion-quality-gate.d.ts +18 -0
  89. package/dist/generator/assertion-quality-gate.d.ts.map +1 -0
  90. package/dist/generator/candidate-writer.d.ts +34 -0
  91. package/dist/generator/candidate-writer.d.ts.map +1 -0
  92. package/dist/generator/test-generator.d.ts +26 -0
  93. package/dist/generator/test-generator.d.ts.map +1 -0
  94. package/dist/governance/audit-log.d.ts +23 -0
  95. package/dist/governance/audit-log.d.ts.map +1 -0
  96. package/dist/governance/governance-policy.d.ts +24 -0
  97. package/dist/governance/governance-policy.d.ts.map +1 -0
  98. package/dist/governance/team-dashboard.d.ts +51 -0
  99. package/dist/governance/team-dashboard.d.ts.map +1 -0
  100. package/dist/governance/workflow-audit.d.ts +13 -0
  101. package/dist/governance/workflow-audit.d.ts.map +1 -0
  102. package/dist/index.d.ts +90 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +20318 -0
  105. package/dist/integrations/ci-summary.d.ts +14 -0
  106. package/dist/integrations/ci-summary.d.ts.map +1 -0
  107. package/dist/integrations/playwright-report-adapter.d.ts +22 -0
  108. package/dist/integrations/playwright-report-adapter.d.ts.map +1 -0
  109. package/dist/integrations/quality-gate.d.ts +35 -0
  110. package/dist/integrations/quality-gate.d.ts.map +1 -0
  111. package/dist/integrations/sarif-report.d.ts +48 -0
  112. package/dist/integrations/sarif-report.d.ts.map +1 -0
  113. package/dist/intelligence/autonomous-repair-workflow.d.ts +31 -0
  114. package/dist/intelligence/autonomous-repair-workflow.d.ts.map +1 -0
  115. package/dist/intelligence/business-intent.d.ts +58 -0
  116. package/dist/intelligence/business-intent.d.ts.map +1 -0
  117. package/dist/intelligence/evidence-bundle.d.ts +364 -0
  118. package/dist/intelligence/evidence-bundle.d.ts.map +1 -0
  119. package/dist/intelligence/failure-clustering.d.ts +38 -0
  120. package/dist/intelligence/failure-clustering.d.ts.map +1 -0
  121. package/dist/intelligence/generation-agent.d.ts +120 -0
  122. package/dist/intelligence/generation-agent.d.ts.map +1 -0
  123. package/dist/intelligence/generation-verifier.d.ts +151 -0
  124. package/dist/intelligence/generation-verifier.d.ts.map +1 -0
  125. package/dist/intelligence/llm-proposal.d.ts +377 -0
  126. package/dist/intelligence/llm-proposal.d.ts.map +1 -0
  127. package/dist/intelligence/locator-disambiguation-engine.d.ts +38 -0
  128. package/dist/intelligence/locator-disambiguation-engine.d.ts.map +1 -0
  129. package/dist/intelligence/model-contract.d.ts +86 -0
  130. package/dist/intelligence/model-contract.d.ts.map +1 -0
  131. package/dist/intelligence/model-provider.d.ts +75 -0
  132. package/dist/intelligence/model-provider.d.ts.map +1 -0
  133. package/dist/intelligence/project-intelligence.d.ts +22 -0
  134. package/dist/intelligence/project-intelligence.d.ts.map +1 -0
  135. package/dist/intelligence/repair-agent.d.ts +46 -0
  136. package/dist/intelligence/repair-agent.d.ts.map +1 -0
  137. package/dist/intelligence/repository-profile.d.ts +131 -0
  138. package/dist/intelligence/repository-profile.d.ts.map +1 -0
  139. package/dist/intelligence/suite-intelligence.d.ts +59 -0
  140. package/dist/intelligence/suite-intelligence.d.ts.map +1 -0
  141. package/dist/intelligence/test-intelligence.d.ts +44 -0
  142. package/dist/intelligence/test-intelligence.d.ts.map +1 -0
  143. package/dist/intelligence/trace-proposal-workflow.d.ts +30 -0
  144. package/dist/intelligence/trace-proposal-workflow.d.ts.map +1 -0
  145. package/dist/intelligence/verified-llm-repair-workflow.d.ts +21 -0
  146. package/dist/intelligence/verified-llm-repair-workflow.d.ts.map +1 -0
  147. package/dist/intelligence/workflow-planner.d.ts +278 -0
  148. package/dist/intelligence/workflow-planner.d.ts.map +1 -0
  149. package/dist/mcp/server.d.ts +32 -0
  150. package/dist/mcp/server.d.ts.map +1 -0
  151. package/dist/memory/stability-ledger.d.ts +46 -0
  152. package/dist/memory/stability-ledger.d.ts.map +1 -0
  153. package/dist/perception/app-model.d.ts +55 -0
  154. package/dist/perception/app-model.d.ts.map +1 -0
  155. package/dist/perception/crawler.d.ts +18 -0
  156. package/dist/perception/crawler.d.ts.map +1 -0
  157. package/dist/perception/index.d.ts +3 -0
  158. package/dist/perception/index.d.ts.map +1 -0
  159. package/dist/repair/approval-service.d.ts +139 -0
  160. package/dist/repair/approval-service.d.ts.map +1 -0
  161. package/dist/repair/assertion-hasher.d.ts +62 -0
  162. package/dist/repair/assertion-hasher.d.ts.map +1 -0
  163. package/dist/repair/ast-patcher.d.ts +36 -0
  164. package/dist/repair/ast-patcher.d.ts.map +1 -0
  165. package/dist/repair/browser-operation-executor.d.ts +27 -0
  166. package/dist/repair/browser-operation-executor.d.ts.map +1 -0
  167. package/dist/repair/diff-allowlist.d.ts +74 -0
  168. package/dist/repair/diff-allowlist.d.ts.map +1 -0
  169. package/dist/repair/intent-validator.d.ts +157 -0
  170. package/dist/repair/intent-validator.d.ts.map +1 -0
  171. package/dist/repair/repair-operations.d.ts +40 -0
  172. package/dist/repair/repair-operations.d.ts.map +1 -0
  173. package/dist/repair/repair-planner.d.ts +98 -0
  174. package/dist/repair/repair-planner.d.ts.map +1 -0
  175. package/dist/repair/repair-workflow.d.ts +42 -0
  176. package/dist/repair/repair-workflow.d.ts.map +1 -0
  177. package/dist/repair/safe-operation-compiler.d.ts +15 -0
  178. package/dist/repair/safe-operation-compiler.d.ts.map +1 -0
  179. package/dist/repair/source-mapper.d.ts +19 -0
  180. package/dist/repair/source-mapper.d.ts.map +1 -0
  181. package/dist/repair/statement-patcher.d.ts +75 -0
  182. package/dist/repair/statement-patcher.d.ts.map +1 -0
  183. package/dist/repair/verification-gates.d.ts +25 -0
  184. package/dist/repair/verification-gates.d.ts.map +1 -0
  185. package/dist/repair/workflow-plan.d.ts +35 -0
  186. package/dist/repair/workflow-plan.d.ts.map +1 -0
  187. package/dist/repair/workspace-promoter.d.ts +43 -0
  188. package/dist/repair/workspace-promoter.d.ts.map +1 -0
  189. package/dist/reproduce/diagnostic-rerunner.d.ts +40 -0
  190. package/dist/reproduce/diagnostic-rerunner.d.ts.map +1 -0
  191. package/dist/reproduce/direct-browser-investigator.d.ts +41 -0
  192. package/dist/reproduce/direct-browser-investigator.d.ts.map +1 -0
  193. package/dist/reproduce/interactive-workflow-runner.d.ts +43 -0
  194. package/dist/reproduce/interactive-workflow-runner.d.ts.map +1 -0
  195. package/dist/sandbox/dependency-strategy.d.ts +45 -0
  196. package/dist/sandbox/dependency-strategy.d.ts.map +1 -0
  197. package/dist/sandbox/execution-runner.d.ts +81 -0
  198. package/dist/sandbox/execution-runner.d.ts.map +1 -0
  199. package/dist/sandbox/worktree-manager.d.ts +51 -0
  200. package/dist/sandbox/worktree-manager.d.ts.map +1 -0
  201. package/dist/selector/abstention-policy.d.ts +34 -0
  202. package/dist/selector/abstention-policy.d.ts.map +1 -0
  203. package/dist/selector/candidate-extractor.d.ts +71 -0
  204. package/dist/selector/candidate-extractor.d.ts.map +1 -0
  205. package/dist/selector/live-locator-verifier.d.ts +28 -0
  206. package/dist/selector/live-locator-verifier.d.ts.map +1 -0
  207. package/dist/selector/repair-candidate-ranker.d.ts +10 -0
  208. package/dist/selector/repair-candidate-ranker.d.ts.map +1 -0
  209. package/dist/selector/selector-scorer.d.ts +43 -0
  210. package/dist/selector/selector-scorer.d.ts.map +1 -0
  211. package/dist/trace/adapters/adapter-registry.d.ts +18 -0
  212. package/dist/trace/adapters/adapter-registry.d.ts.map +1 -0
  213. package/dist/trace/adapters/trace-adapter.d.ts +21 -0
  214. package/dist/trace/adapters/trace-adapter.d.ts.map +1 -0
  215. package/dist/trace/adapters/unknown-adapter.d.ts +10 -0
  216. package/dist/trace/adapters/unknown-adapter.d.ts.map +1 -0
  217. package/dist/trace/adapters/v10-adapter.d.ts +10 -0
  218. package/dist/trace/adapters/v10-adapter.d.ts.map +1 -0
  219. package/dist/trace/adapters/v4-adapter.d.ts +11 -0
  220. package/dist/trace/adapters/v4-adapter.d.ts.map +1 -0
  221. package/dist/trace/adapters/v8-adapter.d.ts +10 -0
  222. package/dist/trace/adapters/v8-adapter.d.ts.map +1 -0
  223. package/dist/trace/adapters/v9-adapter.d.ts +10 -0
  224. package/dist/trace/adapters/v9-adapter.d.ts.map +1 -0
  225. package/dist/trace/archive-reader.d.ts +44 -0
  226. package/dist/trace/archive-reader.d.ts.map +1 -0
  227. package/dist/trace/snapshot-resolver.d.ts +55 -0
  228. package/dist/trace/snapshot-resolver.d.ts.map +1 -0
  229. package/dist/trace/trace-parser.d.ts +50 -0
  230. package/dist/trace/trace-parser.d.ts.map +1 -0
  231. package/dist/trace/version-detector.d.ts +20 -0
  232. package/dist/trace/version-detector.d.ts.map +1 -0
  233. package/package.json +76 -6
  234. package/skills/README.md +20 -0
  235. package/skills/pie-failure-investigation/SKILL.md +16 -0
  236. package/skills/pie-quality-engineer/SKILL.md +66 -0
  237. package/skills/pie-release-readiness/SKILL.md +22 -0
  238. package/skills/pie-repair-review/SKILL.md +21 -0
  239. package/skills/pie-trace-to-repair/SKILL.md +35 -0
  240. package/src/authoring/author.ts +81 -0
  241. package/src/authoring/generation-contract.ts +283 -0
  242. package/src/authoring/hybrid-author.ts +115 -0
  243. package/src/authoring/index.ts +7 -0
  244. package/src/authoring/llm-author.ts +282 -0
  245. package/src/authoring/naming/index.ts +4 -0
  246. package/src/authoring/naming/name-plan.ts +28 -0
  247. package/src/authoring/naming/name-planner.ts +339 -0
  248. package/src/authoring/naming/naming-linter.ts +292 -0
  249. package/src/authoring/template-author.ts +39 -0
  250. package/src/cli/index.ts +1172 -0
  251. package/src/collectors/collector-interface.ts +8 -0
  252. package/src/collectors/environment-collector.ts +103 -0
  253. package/src/collectors/error-collector.ts +177 -0
  254. package/src/collectors/git-diff-collector.ts +190 -0
  255. package/src/collectors/live-browser-collector.ts +412 -0
  256. package/src/collectors/network-collector.ts +90 -0
  257. package/src/collectors/static-ast-collector.ts +226 -0
  258. package/src/collectors/trace-collector.ts +66 -0
  259. package/src/config/project-config.ts +114 -0
  260. package/src/core/errors/engine-errors.ts +90 -0
  261. package/src/core/types/diagnostic-context.ts +94 -0
  262. package/src/core/types/repair-evidence.ts +45 -0
  263. package/src/core/version.ts +25 -0
  264. package/src/diagnostics/diagnostic-contract.ts +79 -0
  265. package/src/diagnostics/diagnostic-report.ts +204 -0
  266. package/src/diagnostics/evidence-correlator.ts +117 -0
  267. package/src/diagnostics/external-failure-evidence.ts +72 -0
  268. package/src/diagnostics/failure-category.ts +40 -0
  269. package/src/diagnostics/failure-classifier.ts +701 -0
  270. package/src/evaluation/evaluation-scorecard.ts +198 -0
  271. package/src/evaluation/repository-inspector.ts +143 -0
  272. package/src/evaluation/repository-runner.ts +197 -0
  273. package/src/evidence/evidence-model.ts +76 -0
  274. package/src/evidence/evidence-normalizer.ts +322 -0
  275. package/src/evidence/evidence-redactor.ts +218 -0
  276. package/src/framework/config-adapter.ts +131 -0
  277. package/src/gate/index.ts +43 -0
  278. package/src/gate/oracle.ts +69 -0
  279. package/src/gate/quality.ts +101 -0
  280. package/src/gate/safety.ts +94 -0
  281. package/src/generator/architecture-generator.ts +582 -0
  282. package/src/generator/assertion-quality-gate.ts +88 -0
  283. package/src/generator/candidate-writer.ts +288 -0
  284. package/src/generator/test-generator.ts +52 -0
  285. package/src/governance/audit-log.ts +115 -0
  286. package/src/governance/governance-policy.ts +72 -0
  287. package/src/governance/team-dashboard.ts +189 -0
  288. package/src/governance/workflow-audit.ts +72 -0
  289. package/src/index.ts +107 -0
  290. package/src/integrations/ci-summary.ts +37 -0
  291. package/src/integrations/playwright-report-adapter.ts +173 -0
  292. package/src/integrations/quality-gate.ts +95 -0
  293. package/src/integrations/sarif-report.ts +110 -0
  294. package/src/intelligence/autonomous-repair-workflow.ts +139 -0
  295. package/src/intelligence/business-intent.ts +163 -0
  296. package/src/intelligence/evidence-bundle.ts +300 -0
  297. package/src/intelligence/failure-clustering.ts +134 -0
  298. package/src/intelligence/generation-agent.ts +561 -0
  299. package/src/intelligence/generation-verifier.ts +1115 -0
  300. package/src/intelligence/llm-proposal.ts +519 -0
  301. package/src/intelligence/locator-disambiguation-engine.ts +331 -0
  302. package/src/intelligence/model-contract.ts +205 -0
  303. package/src/intelligence/model-provider.ts +348 -0
  304. package/src/intelligence/project-intelligence.ts +140 -0
  305. package/src/intelligence/repair-agent.ts +297 -0
  306. package/src/intelligence/repository-profile.ts +796 -0
  307. package/src/intelligence/suite-intelligence.ts +305 -0
  308. package/src/intelligence/test-intelligence.ts +136 -0
  309. package/src/intelligence/trace-proposal-workflow.ts +318 -0
  310. package/src/intelligence/verified-llm-repair-workflow.ts +48 -0
  311. package/src/intelligence/workflow-planner.ts +966 -0
  312. package/src/mcp/server.ts +970 -0
  313. package/src/memory/stability-ledger.ts +243 -0
  314. package/src/perception/app-model.ts +32 -0
  315. package/src/perception/crawler.ts +263 -0
  316. package/src/perception/index.ts +3 -0
  317. package/src/repair/approval-service.ts +541 -0
  318. package/src/repair/assertion-hasher.ts +386 -0
  319. package/src/repair/ast-patcher.ts +223 -0
  320. package/src/repair/browser-operation-executor.ts +263 -0
  321. package/src/repair/diff-allowlist.ts +612 -0
  322. package/src/repair/intent-validator.ts +761 -0
  323. package/src/repair/repair-operations.ts +65 -0
  324. package/src/repair/repair-planner.ts +467 -0
  325. package/src/repair/repair-workflow.ts +241 -0
  326. package/src/repair/safe-operation-compiler.ts +68 -0
  327. package/src/repair/source-mapper.ts +156 -0
  328. package/src/repair/statement-patcher.ts +544 -0
  329. package/src/repair/verification-gates.ts +46 -0
  330. package/src/repair/workflow-plan.ts +59 -0
  331. package/src/repair/workspace-promoter.ts +313 -0
  332. package/src/reproduce/diagnostic-rerunner.ts +287 -0
  333. package/src/reproduce/direct-browser-investigator.ts +208 -0
  334. package/src/reproduce/interactive-workflow-runner.ts +828 -0
  335. package/src/sandbox/dependency-strategy.ts +215 -0
  336. package/src/sandbox/execution-runner.ts +408 -0
  337. package/src/sandbox/worktree-manager.ts +287 -0
  338. package/src/selector/abstention-policy.ts +175 -0
  339. package/src/selector/candidate-extractor.ts +343 -0
  340. package/src/selector/live-locator-verifier.ts +139 -0
  341. package/src/selector/repair-candidate-ranker.ts +92 -0
  342. package/src/selector/selector-scorer.ts +344 -0
  343. package/src/trace/adapters/adapter-registry.ts +49 -0
  344. package/src/trace/adapters/trace-adapter.ts +28 -0
  345. package/src/trace/adapters/unknown-adapter.ts +50 -0
  346. package/src/trace/adapters/v10-adapter.ts +39 -0
  347. package/src/trace/adapters/v4-adapter.ts +31 -0
  348. package/src/trace/adapters/v8-adapter.ts +42 -0
  349. package/src/trace/adapters/v9-adapter.ts +39 -0
  350. package/src/trace/archive-reader.ts +246 -0
  351. package/src/trace/snapshot-resolver.ts +308 -0
  352. package/src/trace/trace-parser.ts +467 -0
  353. package/src/trace/version-detector.ts +81 -0
@@ -0,0 +1,322 @@
1
+ import {
2
+ UnifiedEvidenceRecord,
3
+ EvidenceScorecard,
4
+ EvidenceSource,
5
+ } from './evidence-model.js';
6
+ import {
7
+ DiagnosticContext,
8
+ NetworkEvent,
9
+ ConsoleEvent,
10
+ FailedAction,
11
+ } from '../core/types/diagnostic-context.js';
12
+
13
+ export class EvidenceNormalizer {
14
+ private static readonly ALL_SOURCES: EvidenceSource[] = [
15
+ 'trace',
16
+ 'live-browser',
17
+ 'console',
18
+ 'network',
19
+ 'static-ast',
20
+ 'git-diff',
21
+ 'environment',
22
+ 'error',
23
+ ];
24
+
25
+ /**
26
+ * Computes an EvidenceScorecard summarizing the presence and completeness of all evidence channels.
27
+ */
28
+ public static calculateScorecard(records: UnifiedEvidenceRecord[]): EvidenceScorecard {
29
+ const presentSources = new Set<EvidenceSource>(records.map((r) => r.source));
30
+
31
+ const playwrightErrorAvailable = records.some(
32
+ (r) => r.source === 'error' || r.evidenceType === 'playwright-error' || Boolean(r.payload?.errorMessage)
33
+ );
34
+ const testSourceAstAvailable = records.some(
35
+ (r) => r.source === 'static-ast' || r.evidenceType === 'ast-analysis'
36
+ );
37
+ const domSnapshotAvailable = records.some(
38
+ (r) => r.evidenceType === 'dom-snapshot' || r.evidenceType === 'accessibility-tree' || Boolean(r.payload?.html || r.payload?.snapshot)
39
+ );
40
+ const consoleEventsAvailable = records.some(
41
+ (r) => r.source === 'console' || r.evidenceType === 'console-entry' || r.evidenceType === 'console-event'
42
+ );
43
+ const networkEventsAvailable = records.some(
44
+ (r) => r.source === 'network' || r.evidenceType === 'http-response' || r.evidenceType === 'http-request'
45
+ );
46
+ const traceArchiveAvailable = records.some((r) => r.source === 'trace');
47
+ const gitHistoryAvailable = records.some((r) => r.source === 'git-diff');
48
+ const environmentMetadataAvailable = records.some((r) => r.source === 'environment');
49
+
50
+ const availableSources = Array.from(presentSources);
51
+ const unavailableSources = EvidenceNormalizer.ALL_SOURCES.filter((s) => !presentSources.has(s));
52
+
53
+ return {
54
+ playwrightErrorAvailable,
55
+ testSourceAstAvailable,
56
+ domSnapshotAvailable,
57
+ consoleEventsAvailable,
58
+ networkEventsAvailable,
59
+ traceArchiveAvailable,
60
+ gitHistoryAvailable,
61
+ environmentMetadataAvailable,
62
+ totalRecordsCount: records.length,
63
+ availableSources,
64
+ unavailableSources,
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Normalizes a collection of multi-source UnifiedEvidenceRecords into a structured DiagnosticContext.
70
+ * This allows the failure classifier and repair pipeline to function without requiring a trace.zip file.
71
+ */
72
+ public static toDiagnosticContext(records: UnifiedEvidenceRecord[]): DiagnosticContext {
73
+ // 1. Extract FailedAction
74
+ let failedAction: FailedAction = {
75
+ callId: 'multi-source-0',
76
+ action: 'unknown',
77
+ };
78
+
79
+ const errorRecord = records.find(
80
+ (r) => r.source === 'error' || r.evidenceType === 'playwright-error'
81
+ );
82
+ if (errorRecord && errorRecord.payload) {
83
+ failedAction = {
84
+ callId: errorRecord.actionId || errorRecord.evidenceId,
85
+ action: errorRecord.payload.action || 'action',
86
+ selector: errorRecord.payload.selector,
87
+ sourceFile: errorRecord.payload.sourceFile,
88
+ line: errorRecord.payload.line,
89
+ column: errorRecord.payload.column,
90
+ errorMessage: errorRecord.payload.errorMessage,
91
+ errorStack: errorRecord.payload.errorStack,
92
+ durationMs: errorRecord.payload.durationMs,
93
+ };
94
+ } else {
95
+ // Fallback to any record with an errorMessage
96
+ const fallbackRecord = records.find((r) => r.payload?.errorMessage);
97
+ if (fallbackRecord) {
98
+ failedAction = {
99
+ callId: fallbackRecord.actionId || fallbackRecord.evidenceId,
100
+ action: fallbackRecord.payload.action || 'action',
101
+ selector: fallbackRecord.payload.selector,
102
+ errorMessage: fallbackRecord.payload.errorMessage,
103
+ };
104
+ }
105
+ }
106
+
107
+ // 2. Extract DOM Snapshots
108
+ const snapshots: { before?: string; action?: string; after?: string } = {};
109
+ const domRecords = records.filter(
110
+ (r) => r.evidenceType === 'dom-snapshot' || r.evidenceType === 'accessibility-tree'
111
+ );
112
+ for (const domRec of domRecords) {
113
+ const html = domRec.payload.html || domRec.payload.snapshot || domRec.payload.content;
114
+ if (html) {
115
+ const phase = domRec.payload.phase || 'action';
116
+ if (phase === 'before') snapshots.before = html;
117
+ else if (phase === 'after') snapshots.after = html;
118
+ else snapshots.action = html;
119
+ }
120
+ }
121
+
122
+ // 3. Extract Network Events
123
+ const networkEvents: NetworkEvent[] = [];
124
+ const networkRecords = records.filter(
125
+ (r) => r.source === 'network' || r.evidenceType === 'http-response' || r.evidenceType === 'http-request'
126
+ );
127
+ for (const netRec of networkRecords) {
128
+ if (netRec.payload?.url) {
129
+ networkEvents.push({
130
+ url: netRec.payload.url,
131
+ method: netRec.payload.method || 'GET',
132
+ status: typeof netRec.payload.status === 'number' ? netRec.payload.status : 0,
133
+ statusText: netRec.payload.statusText,
134
+ headers: netRec.payload.headers,
135
+ timestamp: netRec.timestamp,
136
+ durationMs: netRec.payload.durationMs,
137
+ errorText: netRec.payload.errorText,
138
+ requestId: netRec.requestId || netRec.payload.requestId,
139
+ frameId: netRec.frameId || netRec.payload.frameId,
140
+ resourceType: netRec.payload.resourceType,
141
+ initiator: netRec.payload.initiator,
142
+ });
143
+ }
144
+ }
145
+
146
+ // 4. Extract Console Events
147
+ const consoleEvents: ConsoleEvent[] = [];
148
+ const consoleRecords = records.filter(
149
+ (r) => r.source === 'console' || r.evidenceType === 'console-entry' || r.evidenceType === 'console-event'
150
+ );
151
+ for (const conRec of consoleRecords) {
152
+ if (conRec.payload?.text) {
153
+ consoleEvents.push({
154
+ type: conRec.payload.type || 'log',
155
+ text: conRec.payload.text,
156
+ timestamp: conRec.timestamp,
157
+ location: conRec.payload.location,
158
+ });
159
+ }
160
+ }
161
+
162
+ // 5. Extract Environment Metadata
163
+ const envRecord = records.find((r) => r.source === 'environment');
164
+ const playwrightVersion = envRecord?.payload?.playwrightVersion || '1.40.0';
165
+ const traceFormatVersion = envRecord?.payload?.traceFormatVersion || 0;
166
+
167
+ const hasSnapshots = Object.keys(snapshots).length > 0;
168
+ const hasNetwork = networkEvents.length > 0;
169
+ const hasSource = records.some((r) => r.source === 'static-ast');
170
+
171
+ return {
172
+ playwrightVersion,
173
+ traceFormatVersion,
174
+ failedAction,
175
+ snapshots,
176
+ networkEvents,
177
+ consoleEvents,
178
+ evidenceCompleteness: {
179
+ domAvailable: hasSnapshots,
180
+ networkAvailable: hasNetwork,
181
+ sourceAvailable: hasSource,
182
+ },
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Converts a DiagnosticContext into UnifiedEvidenceRecords.
188
+ */
189
+ public static fromDiagnosticContext(
190
+ context: DiagnosticContext,
191
+ executionId = `exec-${Date.now()}`
192
+ ): UnifiedEvidenceRecord[] {
193
+ const records: UnifiedEvidenceRecord[] = [];
194
+ const now = Date.now();
195
+
196
+ // 1. Error / Failed action
197
+ records.push({
198
+ evidenceId: `err-${context.failedAction.callId || '0'}`,
199
+ executionId,
200
+ source: 'error',
201
+ timestamp: now,
202
+ actionId: context.failedAction.callId,
203
+ evidenceType: 'playwright-error',
204
+ payload: {
205
+ action: context.failedAction.action,
206
+ selector: context.failedAction.selector,
207
+ errorMessage: context.failedAction.errorMessage,
208
+ errorStack: context.failedAction.errorStack,
209
+ sourceFile: context.failedAction.sourceFile,
210
+ line: context.failedAction.line,
211
+ column: context.failedAction.column,
212
+ durationMs: context.failedAction.durationMs,
213
+ },
214
+ reliability: 'HIGH',
215
+ provenance: {
216
+ collector: 'DiagnosticContextBridge',
217
+ collectedAt: now,
218
+ captureMethod: 'context-export',
219
+ },
220
+ redactionStatus: { isRedacted: false },
221
+ });
222
+
223
+ // 2. DOM Snapshots
224
+ for (const [phase, html] of Object.entries(context.snapshots)) {
225
+ if (html) {
226
+ records.push({
227
+ evidenceId: `dom-${phase}-${Date.now()}`,
228
+ executionId,
229
+ source: 'trace',
230
+ timestamp: now,
231
+ evidenceType: 'dom-snapshot',
232
+ payload: { phase, html },
233
+ reliability: 'HIGH',
234
+ provenance: {
235
+ collector: 'DiagnosticContextBridge',
236
+ collectedAt: now,
237
+ captureMethod: 'snapshot-extraction',
238
+ },
239
+ redactionStatus: { isRedacted: false },
240
+ });
241
+ }
242
+ }
243
+
244
+ // 3. Network Events
245
+ let netIdx = 0;
246
+ for (const net of context.networkEvents) {
247
+ records.push({
248
+ evidenceId: `net-${net.requestId || netIdx++}`,
249
+ executionId,
250
+ source: 'network',
251
+ timestamp: net.timestamp || now,
252
+ requestId: net.requestId,
253
+ frameId: net.frameId,
254
+ evidenceType: 'http-response',
255
+ payload: {
256
+ url: net.url,
257
+ method: net.method,
258
+ status: net.status,
259
+ statusText: net.statusText,
260
+ headers: net.headers,
261
+ durationMs: net.durationMs,
262
+ errorText: net.errorText,
263
+ resourceType: net.resourceType,
264
+ initiator: net.initiator,
265
+ },
266
+ reliability: 'HIGH',
267
+ provenance: {
268
+ collector: 'DiagnosticContextBridge',
269
+ collectedAt: now,
270
+ captureMethod: 'network-event',
271
+ },
272
+ redactionStatus: { isRedacted: false },
273
+ });
274
+ }
275
+
276
+ // 4. Console Events
277
+ let conIdx = 0;
278
+ for (const con of context.consoleEvents) {
279
+ records.push({
280
+ evidenceId: `con-${conIdx++}`,
281
+ executionId,
282
+ source: 'console',
283
+ timestamp: con.timestamp || now,
284
+ evidenceType: 'console-entry',
285
+ payload: {
286
+ type: con.type,
287
+ text: con.text,
288
+ location: con.location,
289
+ },
290
+ reliability: 'MEDIUM',
291
+ provenance: {
292
+ collector: 'DiagnosticContextBridge',
293
+ collectedAt: now,
294
+ captureMethod: 'console-event',
295
+ },
296
+ redactionStatus: { isRedacted: false },
297
+ });
298
+ }
299
+
300
+ // 5. Environment
301
+ records.push({
302
+ evidenceId: `env-${Date.now()}`,
303
+ executionId,
304
+ source: 'environment',
305
+ timestamp: now,
306
+ evidenceType: 'environment-metadata',
307
+ payload: {
308
+ playwrightVersion: context.playwrightVersion,
309
+ traceFormatVersion: context.traceFormatVersion,
310
+ },
311
+ reliability: 'HIGH',
312
+ provenance: {
313
+ collector: 'DiagnosticContextBridge',
314
+ collectedAt: now,
315
+ captureMethod: 'environment-probe',
316
+ },
317
+ redactionStatus: { isRedacted: false },
318
+ });
319
+
320
+ return records;
321
+ }
322
+ }
@@ -0,0 +1,218 @@
1
+ import { UnifiedEvidenceRecord, RedactionStatus } from './evidence-model.js';
2
+
3
+ export class EvidenceRedactor {
4
+ private static readonly SENSITIVE_HEADER_KEYS = new Set([
5
+ 'authorization',
6
+ 'cookie',
7
+ 'set-cookie',
8
+ 'x-api-key',
9
+ 'x-auth-token',
10
+ 'proxy-authorization',
11
+ 'proxy-authenticate',
12
+ 'www-authenticate',
13
+ 'session-token',
14
+ 'access-token',
15
+ ]);
16
+
17
+ private static readonly SENSITIVE_FIELD_PATTERNS = [
18
+ /pass(word)?/i,
19
+ /secret/i,
20
+ /token/i,
21
+ /api[_-]?key/i,
22
+ /bearer/i,
23
+ /credit[_-]?card/i,
24
+ /cvv/i,
25
+ /ssn/i,
26
+ /social[_-]?security/i,
27
+ /private[_-]?key/i,
28
+ ];
29
+
30
+ private static readonly PATTERNS = [
31
+ {
32
+ name: 'BEARER_TOKEN',
33
+ regex: /Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi,
34
+ replacement: 'Bearer [REDACTED]',
35
+ },
36
+ {
37
+ name: 'JWT_TOKEN',
38
+ regex: /eyJ[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*/g,
39
+ replacement: '[JWT_TOKEN_REDACTED]',
40
+ },
41
+ {
42
+ name: 'CREDIT_CARD',
43
+ // 13-19 digits with optional spaces or dashes
44
+ regex: /\b(?:\d[ -]*?){13,19}\b/g,
45
+ replacement: '[CARD_REDACTED]',
46
+ },
47
+ {
48
+ name: 'SSN',
49
+ regex: /\b\d{3}-\d{2}-\d{4}\b/g,
50
+ replacement: '[SSN_REDACTED]',
51
+ },
52
+ {
53
+ name: 'BASIC_AUTH_URL',
54
+ regex: /https?:\/\/[^:]+:[^@]+@/gi,
55
+ replacement: 'https://[USER:PASS_REDACTED]@',
56
+ },
57
+ ];
58
+
59
+ /**
60
+ * Redacts sensitive string patterns such as JWT tokens, credit cards, SSNs, and passwords.
61
+ */
62
+ public static redactText(text: string): { redactedText: string; rulesApplied: string[] } {
63
+ if (!text || typeof text !== 'string') {
64
+ return { redactedText: text, rulesApplied: [] };
65
+ }
66
+
67
+ let result = text;
68
+ const rulesApplied: string[] = [];
69
+
70
+ for (const rule of EvidenceRedactor.PATTERNS) {
71
+ if (rule.regex.test(result)) {
72
+ rulesApplied.push(rule.name);
73
+ result = result.replace(rule.regex, rule.replacement);
74
+ }
75
+ // Reset regex state if global
76
+ rule.regex.lastIndex = 0;
77
+ }
78
+
79
+ return { redactedText: result, rulesApplied };
80
+ }
81
+
82
+ /**
83
+ * Redacts sensitive HTTP header maps.
84
+ */
85
+ public static redactHeaders(headers?: Record<string, string>): {
86
+ redactedHeaders: Record<string, string>;
87
+ redactedFields: string[];
88
+ } {
89
+ if (!headers || typeof headers !== 'object') {
90
+ return { redactedHeaders: {}, redactedFields: [] };
91
+ }
92
+
93
+ const redactedHeaders: Record<string, string> = {};
94
+ const redactedFields: string[] = [];
95
+
96
+ for (const [key, value] of Object.entries(headers)) {
97
+ const lower = key.toLowerCase();
98
+ if (EvidenceRedactor.SENSITIVE_HEADER_KEYS.has(lower)) {
99
+ redactedHeaders[key] = '[REDACTED]';
100
+ redactedFields.push(key);
101
+ } else {
102
+ const { redactedText, rulesApplied } = EvidenceRedactor.redactText(String(value));
103
+ redactedHeaders[key] = redactedText;
104
+ if (rulesApplied.length > 0) {
105
+ redactedFields.push(key);
106
+ }
107
+ }
108
+ }
109
+
110
+ return { redactedHeaders, redactedFields };
111
+ }
112
+
113
+ /**
114
+ * Recursively redacts objects, arrays, and primitive payload fields.
115
+ */
116
+ public static redactPayload(payload: any): {
117
+ redactedPayload: any;
118
+ redactedFields: string[];
119
+ rulesApplied: string[];
120
+ } {
121
+ const redactedFields: string[] = [];
122
+ const rulesApplied: string[] = [];
123
+
124
+ function recurse(value: any, path: string): any {
125
+ if (value === null || value === undefined) {
126
+ return value;
127
+ }
128
+
129
+ if (typeof value === 'string') {
130
+ const { redactedText, rulesApplied: applied } = EvidenceRedactor.redactText(value);
131
+ if (applied.length > 0) {
132
+ redactedFields.push(path);
133
+ for (const rule of applied) {
134
+ if (!rulesApplied.includes(rule)) rulesApplied.push(rule);
135
+ }
136
+ }
137
+ return redactedText;
138
+ }
139
+
140
+ if (Array.isArray(value)) {
141
+ return value.map((item, idx) => recurse(item, `${path}[${idx}]`));
142
+ }
143
+
144
+ if (typeof value === 'object') {
145
+ const result: Record<string, any> = {};
146
+ for (const [k, v] of Object.entries(value)) {
147
+ const currentPath = path ? `${path}.${k}` : k;
148
+ const isSensitiveField = EvidenceRedactor.SENSITIVE_FIELD_PATTERNS.some((p) => p.test(k));
149
+
150
+ if (isSensitiveField) {
151
+ result[k] = '[REDACTED]';
152
+ redactedFields.push(currentPath);
153
+ if (!rulesApplied.includes('SENSITIVE_FIELD_KEY')) {
154
+ rulesApplied.push('SENSITIVE_FIELD_KEY');
155
+ }
156
+ } else {
157
+ result[k] = recurse(v, currentPath);
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+
163
+ return value;
164
+ }
165
+
166
+ const redactedPayload = recurse(payload, '');
167
+ return { redactedPayload, redactedFields, rulesApplied };
168
+ }
169
+
170
+ /**
171
+ * Sanitizes DOM HTML strings, scrubbing passwords, secret inputs, tokens, and PII.
172
+ */
173
+ public static redactDomContent(html: string): string {
174
+ if (!html || typeof html !== 'string') return '';
175
+ let clean = html;
176
+ // 1. Password input values
177
+ clean = clean.replace(/(<input[^>]*type=["']password["'][^>]*value=["'])([^"']*)(["'])/gi, '$1[REDACTED]$3');
178
+ // 2. Hidden input tokens
179
+ clean = clean.replace(/(<input[^>]*name=["'](?:csrf|token|secret|auth|apikey|api_key)["'][^>]*value=["'])([^"']*)(["'])/gi, '$1[REDACTED]$3');
180
+ // 3. General pattern redaction (Bearer, JWT, CC, SSN)
181
+ clean = EvidenceRedactor.redactText(clean).redactedText;
182
+ return clean;
183
+ }
184
+
185
+ /**
186
+ * Enforces complete redaction across a UnifiedEvidenceRecord.
187
+ */
188
+ public static redactRecord(record: UnifiedEvidenceRecord): UnifiedEvidenceRecord {
189
+ let rawPayload = record.payload;
190
+ if (record.evidenceType === 'dom-snapshot' && rawPayload?.html) {
191
+ rawPayload = {
192
+ ...rawPayload,
193
+ html: EvidenceRedactor.redactDomContent(rawPayload.html),
194
+ };
195
+ }
196
+
197
+ const { redactedPayload, redactedFields, rulesApplied } = EvidenceRedactor.redactPayload(rawPayload);
198
+
199
+ const existingFields = record.redactionStatus.redactedFields ?? [];
200
+ const existingRules = record.redactionStatus.redactionRulesApplied ?? [];
201
+
202
+ const mergedFields = Array.from(new Set([...existingFields, ...redactedFields]));
203
+ const mergedRules = Array.from(new Set([...existingRules, ...rulesApplied]));
204
+
205
+ const redactionStatus: RedactionStatus = {
206
+ isRedacted: mergedFields.length > 0 || record.redactionStatus.isRedacted,
207
+ redactedFields: mergedFields,
208
+ redactionRulesApplied: mergedRules,
209
+ };
210
+
211
+ return {
212
+ ...record,
213
+ payload: redactedPayload,
214
+ redactionStatus,
215
+ };
216
+ }
217
+ }
218
+
@@ -0,0 +1,131 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { Project, SyntaxKind, ObjectLiteralExpression } from 'ts-morph';
4
+
5
+ export interface PlaywrightConfigSummary {
6
+ configPath: string;
7
+ testDir: string;
8
+ timeoutMs: number;
9
+ retries: number;
10
+ workers?: number | string;
11
+ traceSetting: 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'unknown';
12
+ projects: Array<{ name: string; use?: Record<string, any> }>;
13
+ }
14
+
15
+ export class ConfigAdapter {
16
+ private static readonly CONFIG_NAMES = [
17
+ 'playwright.config.ts',
18
+ 'playwright.config.js',
19
+ 'playwright.config.mjs',
20
+ 'playwright.config.cjs',
21
+ ];
22
+
23
+ /**
24
+ * Finds and summarizes the Playwright config in a repository.
25
+ */
26
+ public static async findConfig(repoDir: string): Promise<PlaywrightConfigSummary | null> {
27
+ for (const name of ConfigAdapter.CONFIG_NAMES) {
28
+ const fullPath = path.resolve(repoDir, name);
29
+ try {
30
+ await fs.access(fullPath);
31
+ return ConfigAdapter.parseConfig(fullPath);
32
+ } catch {
33
+ continue;
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+
39
+ /**
40
+ * Statically parses a playwright.config.ts file via ts-morph AST without evaluating untrusted code.
41
+ */
42
+ public static parseConfig(configPath: string): PlaywrightConfigSummary {
43
+ const project = new Project({ skipAddingFilesFromTsConfig: true });
44
+ const sourceFile = project.addSourceFileAtPath(configPath);
45
+
46
+ let testDir = './tests';
47
+ let timeoutMs = 30000;
48
+ let retries = 0;
49
+ let traceSetting: PlaywrightConfigSummary['traceSetting'] = 'unknown';
50
+ const projects: PlaywrightConfigSummary['projects'] = [];
51
+
52
+ // Look for defineProperty or export default defineConfig({...})
53
+ sourceFile.forEachDescendant((node) => {
54
+ if (node.isKind(SyntaxKind.ObjectLiteralExpression)) {
55
+ const obj = node as ObjectLiteralExpression;
56
+
57
+ const testDirProp = obj.getProperty('testDir');
58
+ if (testDirProp && 'getInitializer' in testDirProp) {
59
+ const init = (testDirProp as any).getInitializer();
60
+ if (init) testDir = init.getText().replace(/['"]/g, '');
61
+ }
62
+
63
+ const timeoutProp = obj.getProperty('timeout');
64
+ if (timeoutProp && 'getInitializer' in timeoutProp) {
65
+ const init = (timeoutProp as any).getInitializer();
66
+ if (init && !isNaN(Number(init.getText()))) {
67
+ timeoutMs = Number(init.getText());
68
+ }
69
+ }
70
+
71
+ const retriesProp = obj.getProperty('retries');
72
+ if (retriesProp && 'getInitializer' in retriesProp) {
73
+ const init = (retriesProp as any).getInitializer();
74
+ if (init && !isNaN(Number(init.getText()))) {
75
+ retries = Number(init.getText());
76
+ }
77
+ }
78
+
79
+ // Check use.trace
80
+ const useProp = obj.getProperty('use');
81
+ if (useProp && 'getInitializer' in useProp) {
82
+ const useInit = (useProp as any).getInitializer();
83
+ if (useInit && useInit.isKind(SyntaxKind.ObjectLiteralExpression)) {
84
+ const traceProp = (useInit as ObjectLiteralExpression).getProperty('trace');
85
+ if (traceProp && 'getInitializer' in traceProp) {
86
+ const traceInit = (traceProp as any).getInitializer();
87
+ const val = traceInit?.getText().replace(/['"]/g, '');
88
+ if (['off', 'on', 'retain-on-failure', 'on-first-retry'].includes(val)) {
89
+ traceSetting = val as any;
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
95
+ });
96
+
97
+ return {
98
+ configPath,
99
+ testDir,
100
+ timeoutMs,
101
+ retries,
102
+ traceSetting,
103
+ projects,
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Generates a temporary verification config string with retries disabled and tracing enabled.
109
+ */
110
+ public static generateVerificationOverride(baseConfigPath?: string): string {
111
+ const importStatement = baseConfigPath
112
+ ? `import baseConfig from './${path.basename(baseConfigPath).replace(/\.ts$/, '')}';\n`
113
+ : `import { defineConfig } from '@playwright/test';\n`;
114
+
115
+ return `${importStatement}
116
+ // Auto-generated by Playwright Intelligence Engine for isolated worktree verification
117
+ export default {
118
+ ...(typeof baseConfig !== 'undefined' ? baseConfig : {}),
119
+ retries: 0, // Deterministic: retries disabled to measure true flakiness
120
+ workers: 1, // Deterministic single-worker isolation
121
+ use: {
122
+ ...(typeof baseConfig !== 'undefined' && baseConfig.use ? baseConfig.use : {}),
123
+ trace: 'retain-on-failure',
124
+ video: 'off',
125
+ screenshot: 'only-on-failure',
126
+ },
127
+ };
128
+ `;
129
+ }
130
+ }
131
+