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,189 @@
1
+ import type { CiEvidenceReport } from '../integrations/playwright-report-adapter.js';
2
+ import { evaluateQualityGate, QualityGatePolicy, QualityGateReport } from '../integrations/quality-gate.js';
3
+ import { FailureCluster } from '../intelligence/failure-clustering.js';
4
+ import { TestStabilitySummary } from '../intelligence/suite-intelligence.js';
5
+
6
+ export interface TeamEvidenceRun {
7
+ runId: string;
8
+ repository: string;
9
+ branch?: string | undefined;
10
+ commit?: string | undefined;
11
+ timestamp?: number | undefined;
12
+ evidence: CiEvidenceReport;
13
+ }
14
+
15
+ export interface RepositoryDashboardSummary {
16
+ repository: string;
17
+ runs: number;
18
+ testRuns: number;
19
+ failures: number;
20
+ flakyTests: number;
21
+ failureClusters: number;
22
+ passRate: number;
23
+ latestStatus: QualityGateReport['status'];
24
+ latestRunId: string;
25
+ }
26
+
27
+ export interface DashboardFlakyTest {
28
+ key: string;
29
+ repository?: string | undefined;
30
+ testId: string;
31
+ title?: string | undefined;
32
+ sourceFile?: string | undefined;
33
+ flakeRate: number;
34
+ runs: number;
35
+ failures: number;
36
+ }
37
+
38
+ export interface TeamDashboardReport {
39
+ generatedAt: string;
40
+ policy: QualityGatePolicy;
41
+ runCount: number;
42
+ repositoryCount: number;
43
+ repositories: RepositoryDashboardSummary[];
44
+ totals: {
45
+ testRuns: number;
46
+ failures: number;
47
+ flakyTests: number;
48
+ failureClusters: number;
49
+ };
50
+ failureClusters: FailureCluster[];
51
+ flakyTests: DashboardFlakyTest[];
52
+ qualityGate: QualityGateReport;
53
+ markdown: string;
54
+ }
55
+
56
+ function round(value: number): number {
57
+ return Number(value.toFixed(3));
58
+ }
59
+
60
+ function severityRank(severity: FailureCluster['severity']): number {
61
+ return { critical: 4, high: 3, medium: 2, low: 1, unknown: 0 }[severity];
62
+ }
63
+
64
+ function aggregateClusters(runs: TeamEvidenceRun[]): FailureCluster[] {
65
+ const grouped = new Map<string, FailureCluster>();
66
+ for (const run of runs) {
67
+ for (const cluster of run.evidence.clusters) {
68
+ const existing = grouped.get(cluster.clusterId);
69
+ if (!existing) {
70
+ grouped.set(cluster.clusterId, {
71
+ ...cluster,
72
+ affectedRepositories: [...new Set([run.repository, ...cluster.affectedRepositories])].sort(),
73
+ affectedTests: [...cluster.affectedTests].sort(),
74
+ observationIds: cluster.observationIds.map((id) => `${run.runId}:${id}`).sort(),
75
+ });
76
+ continue;
77
+ }
78
+ existing.count += cluster.count;
79
+ existing.observationIds.push(...cluster.observationIds.map((id) => `${run.runId}:${id}`));
80
+ existing.observationIds = [...new Set(existing.observationIds)].sort();
81
+ existing.affectedRepositories = [...new Set([...existing.affectedRepositories, run.repository, ...cluster.affectedRepositories])].sort();
82
+ existing.affectedTests = [...new Set([...existing.affectedTests, ...cluster.affectedTests])].sort();
83
+ existing.severity = severityRank(cluster.severity) > severityRank(existing.severity) ? cluster.severity : existing.severity;
84
+ existing.evidenceConsistency = round((existing.evidenceConsistency + cluster.evidenceConsistency) / 2);
85
+ if (cluster.firstSeen !== undefined) existing.firstSeen = existing.firstSeen === undefined ? cluster.firstSeen : Math.min(existing.firstSeen, cluster.firstSeen);
86
+ if (cluster.lastSeen !== undefined) existing.lastSeen = existing.lastSeen === undefined ? cluster.lastSeen : Math.max(existing.lastSeen, cluster.lastSeen);
87
+ }
88
+ }
89
+ return [...grouped.values()].sort((left, right) => severityRank(right.severity) - severityRank(left.severity) || right.count - left.count || left.clusterId.localeCompare(right.clusterId));
90
+ }
91
+
92
+ function aggregateStability(runs: TeamEvidenceRun[]): TestStabilitySummary[] {
93
+ const groups = new Map<string, TestStabilitySummary[]>();
94
+ for (const run of runs) {
95
+ for (const summary of run.evidence.stability) {
96
+ const key = `${run.repository}::${summary.testId}`;
97
+ const group = groups.get(key);
98
+ if (group) group.push({ ...summary, repository: run.repository });
99
+ else groups.set(key, [{ ...summary, repository: run.repository }]);
100
+ }
101
+ }
102
+ return [...groups.entries()].map(([key, summaries]) => {
103
+ const first = summaries[0]!;
104
+ const totalRuns = summaries.reduce((sum, item) => sum + item.runs, 0);
105
+ const passes = summaries.reduce((sum, item) => sum + item.passes, 0);
106
+ const failures = summaries.reduce((sum, item) => sum + item.failures, 0);
107
+ const skips = summaries.reduce((sum, item) => sum + item.skips, 0);
108
+ const blocked = summaries.reduce((sum, item) => sum + item.blocked, 0);
109
+ return {
110
+ ...first,
111
+ testId: first.testId,
112
+ repository: first.repository,
113
+ runs: totalRuns,
114
+ passes,
115
+ failures,
116
+ skips,
117
+ blocked,
118
+ passRate: totalRuns > 0 ? round(passes / totalRuns) : 0,
119
+ flakeRate: totalRuns > 0 ? round(Math.min(passes, failures) / totalRuns) : 0,
120
+ flaky: passes > 0 && failures > 0,
121
+ failureClusters: [...new Set(summaries.flatMap((item) => item.failureClusters))].sort(),
122
+ lastStatus: summaries[summaries.length - 1]!.lastStatus,
123
+ ...(key ? {} : {}),
124
+ };
125
+ });
126
+ }
127
+
128
+ function renderMarkdown(report: Omit<TeamDashboardReport, 'markdown'>): string {
129
+ const lines = [
130
+ `# PIE Team Quality Dashboard — ${report.qualityGate.status}`,
131
+ '',
132
+ `Policy: **${report.policy.name ?? 'default'}**`,
133
+ `Runs: **${report.runCount}** | Repositories: **${report.repositoryCount}** | Test executions: **${report.totals.testRuns}**`,
134
+ `Failures: **${report.totals.failures}** | Flaky tests: **${report.totals.flakyTests}** | Failure clusters: **${report.totals.failureClusters}**`,
135
+ ];
136
+ if (report.qualityGate.reasons.length > 0) lines.push('', '## Gate reasons', ...report.qualityGate.reasons.map((reason) => `- ${reason}`));
137
+ lines.push('', '## Repositories', '| Repository | Runs | Tests | Failures | Flaky | Gate |', '|---|---:|---:|---:|---:|---|');
138
+ for (const repository of report.repositories) lines.push(`| ${repository.repository} | ${repository.runs} | ${repository.testRuns} | ${repository.failures} | ${repository.flakyTests} | ${repository.latestStatus} |`);
139
+ if (report.failureClusters.length > 0) {
140
+ lines.push('', '## Top failure clusters', '| Severity | Count | Category | Repositories |', '|---|---:|---|---|');
141
+ for (const cluster of report.failureClusters.slice(0, 20)) lines.push(`| ${cluster.severity} | ${cluster.count} | ${cluster.fingerprint.category} | ${cluster.affectedRepositories.join(', ') || 'unknown'} |`);
142
+ }
143
+ return lines.join('\n');
144
+ }
145
+
146
+ export function buildTeamDashboard(runs: TeamEvidenceRun[], policy: QualityGatePolicy = {}): TeamDashboardReport {
147
+ const clusters = aggregateClusters(runs);
148
+ const stability = aggregateStability(runs);
149
+ const blockedCount = runs.reduce((sum, run) => sum + run.evidence.qualityGate.blockedCount, 0);
150
+ const requiredOracleUnavailable = runs.reduce((sum, run) => sum + run.evidence.qualityGate.requiredOracleUnavailable, 0);
151
+ const verifiedRepairs = runs.reduce((sum, run) => sum + run.evidence.qualityGate.verifiedRepairs, 0);
152
+ const failedRepairs = runs.reduce((sum, run) => sum + run.evidence.qualityGate.failedRepairs, 0);
153
+ const qualityGate = evaluateQualityGate({ clusters, stability, blockedCount, requiredOracleUnavailable, verifiedRepairs, failedRepairs }, policy);
154
+ const repositoryNames = [...new Set(runs.map((run) => run.repository))].sort();
155
+ const repositories = repositoryNames.map((repository) => {
156
+ const repositoryRuns = runs.filter((run) => run.repository === repository);
157
+ const testRuns = repositoryRuns.reduce((sum, run) => sum + run.evidence.runs.length, 0);
158
+ const failures = repositoryRuns.reduce((sum, run) => sum + run.evidence.failures.length, 0);
159
+ const flakyTests = new Set(repositoryRuns.flatMap((run) => run.evidence.stability.filter((test) => test.flaky).map((test) => test.testId))).size;
160
+ const latest = [...repositoryRuns].sort((left, right) => (right.timestamp ?? 0) - (left.timestamp ?? 0))[0]!;
161
+ return {
162
+ repository,
163
+ runs: repositoryRuns.length,
164
+ testRuns,
165
+ failures,
166
+ flakyTests,
167
+ failureClusters: new Set(repositoryRuns.flatMap((run) => run.evidence.clusters.map((cluster) => cluster.clusterId))).size,
168
+ passRate: testRuns > 0 ? round(repositoryRuns.reduce((sum, run) => sum + run.evidence.runs.filter((test) => test.status === 'PASS').length, 0) / testRuns) : 0,
169
+ latestStatus: latest.evidence.qualityGate.status,
170
+ latestRunId: latest.runId,
171
+ } satisfies RepositoryDashboardSummary;
172
+ });
173
+ const flakyTests = [...new Map(stability.filter((test) => test.flaky).map((test) => {
174
+ const key = `${test.repository ?? 'unknown'}::${test.testId}`;
175
+ return [key, { key, repository: test.repository, testId: test.testId, title: test.title, sourceFile: test.sourceFile, flakeRate: test.flakeRate, runs: test.runs, failures: test.failures } satisfies DashboardFlakyTest];
176
+ })).values()].sort((left, right) => right.flakeRate - left.flakeRate || left.key.localeCompare(right.key));
177
+ const reportBase = {
178
+ generatedAt: new Date().toISOString(),
179
+ policy,
180
+ runCount: runs.length,
181
+ repositoryCount: repositoryNames.length,
182
+ repositories,
183
+ totals: { testRuns: runs.reduce((sum, run) => sum + run.evidence.runs.length, 0), failures: runs.reduce((sum, run) => sum + run.evidence.failures.length, 0), flakyTests: flakyTests.length, failureClusters: clusters.length },
184
+ failureClusters: clusters,
185
+ flakyTests,
186
+ qualityGate,
187
+ };
188
+ return { ...reportBase, markdown: renderMarkdown(reportBase) };
189
+ }
@@ -0,0 +1,72 @@
1
+ import { AuditLog } from './audit-log.js';
2
+ import type { ArchitecturePlan, ArchitectureWriteResult } from '../generator/architecture-generator.js';
3
+ import type { CiEvidenceReport } from '../integrations/playwright-report-adapter.js';
4
+
5
+ export interface RepairWorkflowAuditInput {
6
+ status: 'ABSTAINED' | 'INPUT_REQUIRED' | 'OPERATION_PROPOSAL_ONLY' | 'PROPOSAL_READY' | 'VERIFIED_READY_FOR_APPROVAL' | 'REJECTED';
7
+ category: string;
8
+ proposalId?: string | undefined;
9
+ worktreeId?: string | undefined;
10
+ executionPassed?: boolean | undefined;
11
+ }
12
+
13
+ export async function recordArchitectureWorkflow(
14
+ root: string,
15
+ plan: ArchitecturePlan,
16
+ writeResult?: ArchitectureWriteResult,
17
+ ): Promise<void> {
18
+ await new AuditLog(root).append({
19
+ actor: 'system',
20
+ action: 'architecture_plan',
21
+ outcome: plan.status === 'ABSTAIN' ? 'abstained' : 'allowed',
22
+ target: plan.featureName,
23
+ metadata: {
24
+ mode: plan.mode,
25
+ status: plan.status,
26
+ plannedFiles: plan.files.length,
27
+ createdFiles: writeResult?.written.length ?? 0,
28
+ skippedFiles: writeResult?.skipped.length ?? 0,
29
+ warnings: plan.warnings.length,
30
+ },
31
+ });
32
+ }
33
+
34
+ export async function recordCiWorkflow(root: string, report: CiEvidenceReport): Promise<void> {
35
+ await new AuditLog(root).append({
36
+ actor: 'system',
37
+ action: 'ci_evidence_ingested',
38
+ outcome: report.qualityGate.status === 'PASS' ? 'allowed' : report.qualityGate.status === 'ABSTAIN' ? 'abstained' : 'failed',
39
+ target: report.clusters[0]?.representative.repository ?? 'playwright-report',
40
+ metadata: {
41
+ status: report.qualityGate.status,
42
+ tests: report.runs.length,
43
+ failures: report.failures.length,
44
+ clusters: report.clusters.length,
45
+ flakyTests: report.stability.filter((test) => test.flaky).length,
46
+ criticalClusters: report.qualityGate.criticalClusters,
47
+ },
48
+ });
49
+ }
50
+
51
+ export async function recordRepairWorkflow(root: string, input: RepairWorkflowAuditInput): Promise<void> {
52
+ const outcome = input.status === 'ABSTAINED'
53
+ ? 'abstained'
54
+ : input.status === 'REJECTED'
55
+ ? 'failed'
56
+ : input.status === 'INPUT_REQUIRED'
57
+ ? 'denied'
58
+ : 'allowed';
59
+ await new AuditLog(root).append({
60
+ actor: 'system',
61
+ action: 'repair_workflow',
62
+ outcome,
63
+ target: input.category,
64
+ metadata: {
65
+ status: input.status,
66
+ category: input.category,
67
+ ...(input.proposalId ? { proposalId: input.proposalId } : {}),
68
+ ...(input.worktreeId ? { worktreeId: input.worktreeId } : {}),
69
+ ...(input.executionPassed !== undefined ? { executionPassed: input.executionPassed } : {}),
70
+ },
71
+ });
72
+ }
package/src/index.ts ADDED
@@ -0,0 +1,107 @@
1
+ // Core Types & Schemas
2
+ export * from './core/version.js';
3
+ export * from './core/types/diagnostic-context.js';
4
+ export * from './core/types/repair-evidence.js';
5
+ export * from './core/errors/engine-errors.js';
6
+
7
+ // Trace Ingestion
8
+ export * from './trace/archive-reader.js';
9
+ export * from './trace/version-detector.js';
10
+ export * from './trace/trace-parser.js';
11
+ export * from './trace/snapshot-resolver.js';
12
+ export * from './trace/adapters/trace-adapter.js';
13
+ export * from './trace/adapters/adapter-registry.js';
14
+ export * from './trace/adapters/v8-adapter.js';
15
+ export * from './trace/adapters/v9-adapter.js';
16
+ export * from './trace/adapters/v10-adapter.js';
17
+ export * from './trace/adapters/unknown-adapter.js';
18
+
19
+ // Diagnostics
20
+ export * from './diagnostics/failure-classifier.js';
21
+ export * from './diagnostics/evidence-correlator.js';
22
+ export * from './diagnostics/diagnostic-report.js';
23
+ export * from './diagnostics/diagnostic-contract.js';
24
+ export * from './diagnostics/failure-category.js';
25
+ export * from './diagnostics/external-failure-evidence.js';
26
+
27
+ // Selector Intelligence & Abstention
28
+ export * from './selector/candidate-extractor.js';
29
+ export * from './selector/selector-scorer.js';
30
+ export * from './selector/abstention-policy.js';
31
+ export * from './selector/repair-candidate-ranker.js';
32
+ export * from './intelligence/locator-disambiguation-engine.js';
33
+
34
+ // AST Repair & Verification
35
+ export * from './repair/ast-patcher.js';
36
+ export * from './repair/statement-patcher.js';
37
+ export * from './repair/assertion-hasher.js';
38
+ export * from './repair/diff-allowlist.js';
39
+ export * from './repair/intent-validator.js';
40
+ export * from './repair/repair-planner.js';
41
+ export * from './repair/repair-workflow.js';
42
+ export * from './repair/approval-service.js';
43
+ export * from './repair/workspace-promoter.js';
44
+ export * from './repair/repair-operations.js';
45
+ export * from './repair/verification-gates.js';
46
+ export * from './repair/safe-operation-compiler.js';
47
+ export * from './collectors/git-diff-collector.js';
48
+ export * from './collectors/network-collector.js';
49
+ export * from './collectors/static-ast-collector.js';
50
+ export * from './repair/browser-operation-executor.js';
51
+ export * from './repair/source-mapper.js';
52
+
53
+ // Selector Verification & Live Reproduction
54
+ export * from './selector/live-locator-verifier.js';
55
+ export * from './reproduce/direct-browser-investigator.js';
56
+ export * from './reproduce/diagnostic-rerunner.js';
57
+ export * from './reproduce/interactive-workflow-runner.js';
58
+
59
+ // Sandbox & Worktree Management
60
+ export * from './sandbox/dependency-strategy.js';
61
+ export * from './sandbox/worktree-manager.js';
62
+ export * from './sandbox/execution-runner.js';
63
+
64
+ // Memory & Generation
65
+ export * from './memory/stability-ledger.js';
66
+ export * from './generator/test-generator.js';
67
+ export * from './generator/architecture-generator.js';
68
+ export * from './generator/assertion-quality-gate.js';
69
+ export * from './generator/candidate-writer.js';
70
+ export * from './authoring/index.js';
71
+ export * from './gate/index.js';
72
+ export * from './perception/index.js';
73
+ export * from './config/project-config.js';
74
+ export * from './intelligence/llm-proposal.js';
75
+ export * from './intelligence/model-provider.js';
76
+ export * from './intelligence/model-contract.js';
77
+ export * from './intelligence/evidence-bundle.js';
78
+ export * from './intelligence/repair-agent.js';
79
+ export * from './intelligence/trace-proposal-workflow.js';
80
+ export * from './intelligence/verified-llm-repair-workflow.js';
81
+ export * from './intelligence/autonomous-repair-workflow.js';
82
+ export * from './intelligence/generation-agent.js';
83
+ export * from './intelligence/generation-verifier.js';
84
+ export * from './intelligence/repository-profile.js';
85
+ export * from './intelligence/project-intelligence.js';
86
+ export * from './intelligence/failure-clustering.js';
87
+ export * from './intelligence/suite-intelligence.js';
88
+ export * from './intelligence/business-intent.js';
89
+ export * from './intelligence/test-intelligence.js';
90
+ export * from './intelligence/workflow-planner.js';
91
+ export * from './integrations/ci-summary.js';
92
+ export * from './integrations/quality-gate.js';
93
+ export * from './integrations/playwright-report-adapter.js';
94
+ export * from './integrations/sarif-report.js';
95
+ export * from './governance/audit-log.js';
96
+ export * from './governance/workflow-audit.js';
97
+ export * from './governance/team-dashboard.js';
98
+ export * from './repair/workflow-plan.js';
99
+ export * from './evaluation/repository-inspector.js';
100
+ export * from './evaluation/repository-runner.js';
101
+ export * from './evaluation/evaluation-scorecard.js';
102
+
103
+ // Framework & MCP
104
+ export * from './framework/config-adapter.js';
105
+ export * from './mcp/server.js';
106
+ export * from './cli/index.js';
107
+
@@ -0,0 +1,37 @@
1
+ export interface CiFailureSummary {
2
+ status: 'PASS' | 'FAIL' | 'ABSTAIN' | 'BLOCKED';
3
+ repository?: string;
4
+ testIdentity?: string;
5
+ category?: string;
6
+ confidence?: number;
7
+ reason: string;
8
+ artifacts: string[];
9
+ repairProposalAvailable: boolean;
10
+ verifiedRepair: boolean;
11
+ }
12
+
13
+ export function renderCiSummary(summary: CiFailureSummary): string {
14
+ const lines = [
15
+ `## PIE result: ${summary.status}`,
16
+ '',
17
+ summary.repository ? `- Repository: \`${summary.repository}\`` : undefined,
18
+ summary.testIdentity ? `- Test: \`${summary.testIdentity}\`` : undefined,
19
+ summary.category ? `- Classification: \`${summary.category}\`` : undefined,
20
+ summary.confidence === undefined ? undefined : `- Confidence: ${(summary.confidence * 100).toFixed(1)}%`,
21
+ `- Repair proposal: ${summary.repairProposalAvailable ? 'available' : 'not available'}`,
22
+ `- Browser verification: ${summary.verifiedRepair ? 'passed' : 'not verified'}`,
23
+ `- Reason: ${summary.reason}`,
24
+ ].filter((line): line is string => line !== undefined);
25
+
26
+ if (summary.artifacts.length > 0) {
27
+ lines.push('', '### Artifacts', ...summary.artifacts.map((artifact) => `- ${artifact}`));
28
+ }
29
+
30
+ return lines.join('\n');
31
+ }
32
+
33
+ export function renderGitHubAnnotation(summary: CiFailureSummary): string {
34
+ const level = summary.status === 'FAIL' ? 'error' : summary.status === 'ABSTAIN' ? 'warning' : 'notice';
35
+ return `::${level} title=PIE ${summary.status}::${summary.reason}`;
36
+ }
37
+
@@ -0,0 +1,173 @@
1
+ import { clusterFailures, FailureObservation } from '../intelligence/failure-clustering.js';
2
+ import { analyzeTestStability, TestRunObservation } from '../intelligence/suite-intelligence.js';
3
+ import { evaluateQualityGate, QualityGateReport } from './quality-gate.js';
4
+
5
+ export interface PlaywrightReportAdapterOptions {
6
+ repository?: string | undefined;
7
+ runId?: string | undefined;
8
+ timestamp?: number | undefined;
9
+ }
10
+
11
+ export interface ParsedPlaywrightReport {
12
+ runs: TestRunObservation[];
13
+ failures: FailureObservation[];
14
+ }
15
+
16
+ export interface CiEvidenceReport extends ParsedPlaywrightReport {
17
+ clusters: ReturnType<typeof clusterFailures>;
18
+ stability: ReturnType<typeof analyzeTestStability>;
19
+ qualityGate: QualityGateReport;
20
+ markdown: string;
21
+ annotations: string[];
22
+ }
23
+
24
+ interface PlaywrightResult {
25
+ status?: string | undefined;
26
+ duration?: number | undefined;
27
+ retry?: number | undefined;
28
+ error?: { message?: string; stack?: string } | undefined;
29
+ errors?: Array<{ message?: string; stack?: string }> | undefined;
30
+ }
31
+
32
+ interface PlaywrightTest {
33
+ title?: string | undefined;
34
+ titlePath?: string[] | undefined;
35
+ file?: string | undefined;
36
+ projectName?: string | undefined;
37
+ results?: PlaywrightResult[] | undefined;
38
+ status?: string | undefined;
39
+ }
40
+
41
+ function asObject(value: unknown): Record<string, unknown> {
42
+ return value && typeof value === 'object' ? value as Record<string, unknown> : {};
43
+ }
44
+
45
+ function asString(value: unknown): string | undefined {
46
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
47
+ }
48
+
49
+ function mapStatus(status: string | undefined): TestRunObservation['status'] {
50
+ switch ((status ?? '').toLowerCase()) {
51
+ case 'passed': return 'PASS';
52
+ case 'skipped': return 'SKIP';
53
+ case 'timedout':
54
+ case 'timeout': return 'TIMEOUT';
55
+ case 'interrupted': return 'BLOCKED';
56
+ case 'failed': return 'FAIL';
57
+ default: return 'BLOCKED';
58
+ }
59
+ }
60
+
61
+ function collectTests(node: unknown, inheritedFile: string | undefined, inheritedTitles: string[], output: PlaywrightTest[]): void {
62
+ const object = asObject(node);
63
+ const file = asString(object.file) ?? inheritedFile;
64
+ const title = asString(object.title);
65
+ const titles = title ? [...inheritedTitles, title] : inheritedTitles;
66
+ const specs = Array.isArray(object.specs) ? object.specs : [];
67
+ for (const spec of specs) {
68
+ const specObject = asObject(spec);
69
+ const specTitle = asString(specObject.title);
70
+ const specTitles = specTitle ? [...titles, specTitle] : titles;
71
+ const tests = Array.isArray(specObject.tests) ? specObject.tests : [];
72
+ for (const test of tests) {
73
+ const testObject = asObject(test);
74
+ output.push({
75
+ title: specTitles.join(' › '),
76
+ titlePath: specTitles,
77
+ file: asString(testObject.location) ?? file,
78
+ projectName: asString(testObject.projectName),
79
+ results: Array.isArray(testObject.results) ? testObject.results.map((result) => asObject(result) as PlaywrightResult) : [],
80
+ status: asString(testObject.status),
81
+ });
82
+ }
83
+ }
84
+ const suites = Array.isArray(object.suites) ? object.suites : [];
85
+ for (const suite of suites) collectTests(suite, file, titles, output);
86
+ }
87
+
88
+ function failureMessage(result: PlaywrightResult): { message?: string; stack?: string } {
89
+ const first = result.error ?? result.errors?.[0];
90
+ return {
91
+ ...(first?.message !== undefined ? { message: first.message } : {}),
92
+ ...(first?.stack !== undefined ? { stack: first.stack } : {}),
93
+ };
94
+ }
95
+
96
+ export function parsePlaywrightJsonReport(report: unknown, options: PlaywrightReportAdapterOptions = {}): ParsedPlaywrightReport {
97
+ const root = asObject(report);
98
+ const tests: PlaywrightTest[] = [];
99
+ if (Array.isArray(root.suites)) {
100
+ for (const suite of root.suites) collectTests(suite, undefined, [], tests);
101
+ } else if (Array.isArray(root.tests)) {
102
+ collectTests(root, undefined, [], tests);
103
+ }
104
+
105
+ const runId = options.runId ?? `playwright-${options.timestamp ?? Date.now()}`;
106
+ const timestamp = options.timestamp;
107
+ const runs: TestRunObservation[] = [];
108
+ const failures: FailureObservation[] = [];
109
+ tests.forEach((test, testIndex) => {
110
+ const results: PlaywrightResult[] = test.results && test.results.length > 0 ? test.results : [{ status: test.status }];
111
+ results.forEach((result, resultIndex) => {
112
+ const status = mapStatus(result.status);
113
+ const testId = `${test.file ?? 'unknown'}::${test.title ?? `test-${testIndex + 1}`}`;
114
+ const retryIndex = typeof result.retry === 'number' ? result.retry : resultIndex;
115
+ runs.push({
116
+ runId,
117
+ testId,
118
+ repository: options.repository,
119
+ title: test.title,
120
+ sourceFile: test.file,
121
+ status,
122
+ durationMs: typeof result.duration === 'number' ? result.duration : undefined,
123
+ timestamp,
124
+ retryIndex,
125
+ });
126
+ if (status === 'FAIL' || status === 'TIMEOUT') {
127
+ const error = failureMessage(result);
128
+ failures.push({
129
+ id: `${runId}:${testIndex}:${resultIndex}`,
130
+ repository: options.repository,
131
+ testTitle: test.title,
132
+ sourceFile: test.file,
133
+ category: 'TEST_FAILURE',
134
+ errorMessage: error.message,
135
+ errorStack: error.stack,
136
+ timestamp,
137
+ durationMs: typeof result.duration === 'number' ? result.duration : undefined,
138
+ });
139
+ }
140
+ });
141
+ });
142
+ return { runs, failures };
143
+ }
144
+
145
+ function renderMarkdown(report: Omit<CiEvidenceReport, 'markdown' | 'annotations'>): string {
146
+ const lines = [
147
+ `## PIE CI result: ${report.qualityGate.status}`,
148
+ '',
149
+ `- Tests observed: ${report.runs.length}`,
150
+ `- Failure observations: ${report.failures.length}`,
151
+ `- Failure clusters: ${report.clusters.length}`,
152
+ `- Flaky tests: ${report.stability.filter((test) => test.flaky).length}`,
153
+ ];
154
+ if (report.qualityGate.reasons.length > 0) lines.push('', '### Gate reasons', ...report.qualityGate.reasons.map((reason) => `- ${reason}`));
155
+ if (report.clusters.length > 0) {
156
+ lines.push('', '### Failure clusters', '| Severity | Count | Category | Cluster |', '|---|---:|---|---|');
157
+ for (const cluster of report.clusters.slice(0, 20)) lines.push(`| ${cluster.severity} | ${cluster.count} | ${cluster.fingerprint.category} | ${cluster.clusterId} |`);
158
+ }
159
+ return lines.join('\n');
160
+ }
161
+
162
+ export function buildCiEvidenceReport(report: unknown, options: PlaywrightReportAdapterOptions = {}): CiEvidenceReport {
163
+ const parsed = parsePlaywrightJsonReport(report, options);
164
+ const clusters = clusterFailures(parsed.failures);
165
+ const stability = analyzeTestStability(parsed.runs.map((run) => ({
166
+ ...run,
167
+ failureClusterId: clusters.find((cluster) => run.title && cluster.affectedTests.includes(run.title))?.clusterId,
168
+ })));
169
+ const qualityGate = evaluateQualityGate({ clusters, stability });
170
+ const base = { ...parsed, clusters, stability, qualityGate };
171
+ const annotations = qualityGate.reasons.map((reason) => `::${qualityGate.status === 'FAIL' ? 'error' : qualityGate.status === 'ABSTAIN' ? 'warning' : 'notice'} title=PIE ${qualityGate.status}::${reason}`);
172
+ return { ...base, markdown: renderMarkdown(base), annotations };
173
+ }
@@ -0,0 +1,95 @@
1
+ import { FailureCluster } from '../intelligence/failure-clustering.js';
2
+ import { TestStabilitySummary } from '../intelligence/suite-intelligence.js';
3
+
4
+ export interface QualityGateInput {
5
+ clusters?: FailureCluster[] | undefined;
6
+ stability?: TestStabilitySummary[] | undefined;
7
+ blockedCount?: number | undefined;
8
+ requiredOracleUnavailable?: number | undefined;
9
+ verifiedRepairs?: number | undefined;
10
+ failedRepairs?: number | undefined;
11
+ }
12
+
13
+ /**
14
+ * Optional team policy. When omitted, evaluateQualityGate preserves the
15
+ * original evidence-driven behavior used by local diagnosis and CI reports.
16
+ */
17
+ export interface QualityGatePolicy {
18
+ name?: string | undefined;
19
+ maxFlakyTests?: number | undefined;
20
+ maxHighSeverityClusters?: number | undefined;
21
+ maxBlockedResults?: number | undefined;
22
+ failOnAbstain?: boolean | undefined;
23
+ }
24
+
25
+ export interface QualityGateReport {
26
+ status: 'PASS' | 'FAIL' | 'ABSTAIN' | 'BLOCKED';
27
+ reasons: string[];
28
+ criticalClusters: number;
29
+ highSeverityClusters: number;
30
+ flakyTests: number;
31
+ blockedCount: number;
32
+ requiredOracleUnavailable: number;
33
+ verifiedRepairs: number;
34
+ failedRepairs: number;
35
+ policyViolations: string[];
36
+ }
37
+
38
+ export function evaluateQualityGate(input: QualityGateInput, policy: QualityGatePolicy = {}): QualityGateReport {
39
+ const clusters = input.clusters ?? [];
40
+ const stability = input.stability ?? [];
41
+ const blockedCount = input.blockedCount ?? 0;
42
+ const requiredOracleUnavailable = input.requiredOracleUnavailable ?? 0;
43
+ const verifiedRepairs = input.verifiedRepairs ?? 0;
44
+ const failedRepairs = input.failedRepairs ?? 0;
45
+ const criticalClusters = clusters.filter((cluster) => cluster.severity === 'critical').length;
46
+ const highSeverityClusters = clusters.filter((cluster) => cluster.severity === 'high').length;
47
+ const flakyTests = stability.filter((summary) => summary.flaky).length;
48
+ const reasons: string[] = [];
49
+
50
+ if (criticalClusters > 0) reasons.push(`${criticalClusters} critical failure cluster(s) detected`);
51
+ if (failedRepairs > 0) reasons.push(`${failedRepairs} repair verification(s) failed`);
52
+ if (blockedCount > 0) reasons.push(`${blockedCount} test or repository result(s) are blocked`);
53
+ if (requiredOracleUnavailable > 0) reasons.push(`${requiredOracleUnavailable} required business oracle result(s) are unavailable`);
54
+ if (highSeverityClusters > 0) reasons.push(`${highSeverityClusters} high-severity failure cluster(s) detected`);
55
+ if (flakyTests > 0) reasons.push(`${flakyTests} flaky test(s) detected`);
56
+
57
+ const policyViolations: string[] = [];
58
+ if (policy.maxFlakyTests !== undefined && flakyTests > policy.maxFlakyTests) {
59
+ policyViolations.push(`Policy '${policy.name ?? 'default'}' allows at most ${policy.maxFlakyTests} flaky test(s), found ${flakyTests}`);
60
+ }
61
+ if (policy.maxHighSeverityClusters !== undefined && highSeverityClusters > policy.maxHighSeverityClusters) {
62
+ policyViolations.push(`Policy '${policy.name ?? 'default'}' allows at most ${policy.maxHighSeverityClusters} high-severity cluster(s), found ${highSeverityClusters}`);
63
+ }
64
+ if (policy.maxBlockedResults !== undefined && blockedCount > policy.maxBlockedResults) {
65
+ policyViolations.push(`Policy '${policy.name ?? 'default'}' allows at most ${policy.maxBlockedResults} blocked result(s), found ${blockedCount}`);
66
+ }
67
+ reasons.push(...policyViolations);
68
+
69
+ const evidenceStatus: QualityGateReport['status'] = criticalClusters > 0 || failedRepairs > 0
70
+ ? 'FAIL'
71
+ : blockedCount > 0
72
+ ? 'BLOCKED'
73
+ : requiredOracleUnavailable > 0 || highSeverityClusters > 0 || flakyTests > 0
74
+ ? 'ABSTAIN'
75
+ : 'PASS';
76
+ const status: QualityGateReport['status'] = policyViolations.length > 0 || (policy.failOnAbstain === true && evidenceStatus === 'ABSTAIN')
77
+ ? 'FAIL'
78
+ : evidenceStatus;
79
+ if (policy.failOnAbstain === true && evidenceStatus === 'ABSTAIN' && policyViolations.length === 0) {
80
+ reasons.push(`Policy '${policy.name ?? 'default'}' rejects ABSTAIN outcomes`);
81
+ }
82
+
83
+ return {
84
+ status,
85
+ reasons,
86
+ criticalClusters,
87
+ highSeverityClusters,
88
+ flakyTests,
89
+ blockedCount,
90
+ requiredOracleUnavailable,
91
+ verifiedRepairs,
92
+ failedRepairs,
93
+ policyViolations,
94
+ };
95
+ }