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,318 @@
1
+ import fs from 'node:fs/promises';
2
+ import fsSync from 'node:fs';
3
+ import path from 'node:path';
4
+ import { ArchiveReader } from '../trace/archive-reader.js';
5
+ import { TraceParser } from '../trace/trace-parser.js';
6
+ import { EvidenceCorrelator } from '../diagnostics/evidence-correlator.js';
7
+ import { parseExternalFailureEvidence, supplementDiagnosticContext } from '../diagnostics/external-failure-evidence.js';
8
+ import { buildEvidenceBundle } from './evidence-bundle.js';
9
+ import { runRepairProposalAgent, RepairAgentResult } from './repair-agent.js';
10
+ import { OpenAiCompatibleProposalProvider, ProposalProvider } from './model-provider.js';
11
+ import { EvidenceBundle } from './llm-proposal.js';
12
+ import { CorrelatedEvidence } from '../diagnostics/evidence-correlator.js';
13
+ import { DiagnosticContext } from '../core/types/diagnostic-context.js';
14
+ import { bootstrapProjectIntelligence, getHistoricalSelectorScore } from './project-intelligence.js';
15
+ import { DiagnosticReportGenerator } from '../diagnostics/diagnostic-report.js';
16
+ import { discoverRepairSourceMapping } from '../repair/source-mapper.js';
17
+ import { DirectBrowserInvestigator } from '../reproduce/direct-browser-investigator.js';
18
+ import { CandidateExtractor } from '../selector/candidate-extractor.js';
19
+ import { RepairCandidateRanker } from '../selector/repair-candidate-ranker.js';
20
+ import { AbstentionPolicy } from '../selector/abstention-policy.js';
21
+ import { EvidenceRedactor } from '../evidence/evidence-redactor.js';
22
+ import { ExecutionRunner } from '../sandbox/execution-runner.js';
23
+
24
+ export interface TraceProposalWorkflowInput {
25
+ tracePath: string;
26
+ workspaceRoot?: string | undefined;
27
+ errorContextPath?: string | undefined;
28
+ executionId?: string | undefined;
29
+ testIdentity?: string | undefined;
30
+ enableBrowserInvestigation?: boolean | undefined;
31
+ browserUrl?: string | undefined;
32
+ browserAllowedHosts?: string[] | undefined;
33
+ enableTestExecution?: boolean | undefined;
34
+ provider?: ProposalProvider | undefined;
35
+ }
36
+
37
+ export interface TraceProposalWorkflowResult {
38
+ context: DiagnosticContext;
39
+ correlated: CorrelatedEvidence;
40
+ bundle: EvidenceBundle;
41
+ agent: RepairAgentResult;
42
+ }
43
+
44
+ function assertWorkspacePath(root: string, target: string, label: string): string {
45
+ const canonicalRoot = fsSync.realpathSync(root);
46
+ const resolved = path.resolve(root, target);
47
+ if (!fsSync.existsSync(resolved)) throw new Error(`${label} not found: '${resolved}'`);
48
+ const canonicalTarget = fsSync.realpathSync(resolved);
49
+ const relative = path.relative(canonicalRoot, canonicalTarget);
50
+ if (relative.startsWith('..') || path.isAbsolute(relative)) throw new Error(`${label} escapes workspace root: '${target}'`);
51
+ return canonicalTarget;
52
+ }
53
+
54
+ function resolveReadOnlyPath(root: string, target: string, label: string): string {
55
+ const resolved = path.isAbsolute(target) ? target : path.resolve(root, target);
56
+ if (!fsSync.existsSync(resolved)) throw new Error(`${label} not found: '${resolved}'`);
57
+ return fsSync.realpathSync(resolved);
58
+ }
59
+
60
+ async function searchRepository(root: string, query: string): Promise<Array<{ filePath: string; line: number; snippet: string }>> {
61
+ const ignored = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', 'test-results', 'playwright-report', '.pie', '.pw-intelligence']);
62
+ const results: Array<{ filePath: string; line: number; snippet: string }> = [];
63
+ const walk = async (directory: string, depth: number): Promise<void> => {
64
+ if (depth > 6 || results.length >= 30) return;
65
+ let entries;
66
+ try { entries = await fs.readdir(directory, { withFileTypes: true }); } catch { return; }
67
+ for (const entry of entries) {
68
+ if (results.length >= 30 || ignored.has(entry.name)) continue;
69
+ const full = path.join(directory, entry.name);
70
+ if (entry.isDirectory()) { await walk(full, depth + 1); continue; }
71
+ if (!/\.(?:ts|tsx|js|jsx|json|md|yaml|yml)$/i.test(entry.name)) continue;
72
+ let content: string;
73
+ try { content = await fs.readFile(full, 'utf8'); } catch { continue; }
74
+ const lines = content.split(/\r?\n/);
75
+ lines.forEach((line, index) => {
76
+ if (results.length >= 30 || !line.toLowerCase().includes(query.toLowerCase())) return;
77
+ results.push({ filePath: path.relative(root, full), line: index + 1, snippet: EvidenceRedactor.redactText(line.slice(0, 500)).redactedText });
78
+ });
79
+ }
80
+ };
81
+ await walk(root, 0);
82
+ return results;
83
+ }
84
+
85
+ function configuredProvider(): ProposalProvider | undefined {
86
+ const apiKey = process.env.PIE_LLM_API_KEY ?? process.env.OPENAI_API_KEY ?? process.env.DEEPSEEK_API_KEY;
87
+ const endpoint = process.env.PIE_LLM_ENDPOINT ?? (process.env.OPENAI_API_KEY ? 'https://api.openai.com/v1/chat/completions' : (apiKey ? 'https://api.deepseek.com/chat/completions' : undefined));
88
+ const model = process.env.PIE_LLM_MODEL ?? (process.env.OPENAI_API_KEY ? 'gpt-4o' : (apiKey ? 'deepseek-chat' : undefined));
89
+ if (!endpoint || !model) return undefined;
90
+ const timeoutRaw = process.env.PIE_LLM_TIMEOUT_MS;
91
+ const timeoutMs = timeoutRaw ? Number(timeoutRaw) : undefined;
92
+ return new OpenAiCompatibleProposalProvider({
93
+ endpoint,
94
+ model,
95
+ ...(apiKey ? { apiKey } : {}),
96
+ ...(Number.isFinite(timeoutMs) && timeoutMs && timeoutMs > 0 ? { timeoutMs } : {}),
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Runs one bounded, redaction-aware model proposal step from a trace archive.
102
+ * Deterministic classification executes before the provider and the returned
103
+ * proposal is never executed or promoted by this function.
104
+ */
105
+ export async function runTraceProposalWorkflow(input: TraceProposalWorkflowInput): Promise<TraceProposalWorkflowResult> {
106
+ const workspaceRoot = path.resolve(input.workspaceRoot ?? process.cwd());
107
+ const tracePath = resolveReadOnlyPath(workspaceRoot, input.tracePath, 'Trace archive');
108
+ const { traceEntryName, networkEntryName, traceEntryNames, networkEntryNames } = ArchiveReader.findTraceFileEntries(tracePath);
109
+ if (!traceEntryName) throw new Error(`No .trace event stream found in archive '${tracePath}'`);
110
+
111
+ const traceText = await ArchiveReader.readEntriesAsText(tracePath, traceEntryNames ?? [traceEntryName]);
112
+ const networkText = (networkEntryNames ?? (networkEntryName ? [networkEntryName] : [])).length > 0
113
+ ? await ArchiveReader.readEntriesAsText(tracePath, networkEntryNames ?? [networkEntryName!])
114
+ : '';
115
+ let context = TraceParser.assembleDiagnosticContext(traceText.split('\n'), networkText.split('\n'));
116
+ if (input.errorContextPath) {
117
+ const errorContextPath = resolveReadOnlyPath(workspaceRoot, input.errorContextPath, 'Error context');
118
+ context = supplementDiagnosticContext(context, parseExternalFailureEvidence(await fs.readFile(errorContextPath, 'utf8')));
119
+ }
120
+
121
+ const correlated = EvidenceCorrelator.correlate(context);
122
+ const intelligence = await bootstrapProjectIntelligence(workspaceRoot);
123
+ const deterministicProposedLocator = DiagnosticReportGenerator.extractProposedLocator(correlated, intelligence);
124
+ const sourceMapping = await discoverRepairSourceMapping({ workspaceRoot, failedAction: correlated.context.failedAction });
125
+ const sourceContext: EvidenceBundle['sourceContext'] = [];
126
+ const profile = intelligence.profile;
127
+ const projectContext = profile
128
+ ? {
129
+ preferredLocator: profile.locatorConventions.preferred,
130
+ usesPageObjects: profile.structure.usesPageObjects,
131
+ usesCustomFixtures: profile.structure.usesCustomFixtures,
132
+ usesStorageState: profile.structure.usesStorageState,
133
+ domainTerms: profile.domainTerms.slice(0, 30),
134
+ ...(context.failedAction.selector
135
+ ? { historicalSelectorReliability: getHistoricalSelectorScore(intelligence, context.failedAction.selector) }
136
+ : {}),
137
+ }
138
+ : undefined;
139
+ if (projectContext) {
140
+ sourceContext.push({ filePath: '.pie/project-intelligence.json', content: JSON.stringify(projectContext, null, 2) });
141
+ }
142
+ if (sourceMapping?.pomFilePath) {
143
+ try {
144
+ const source = await fs.readFile(sourceMapping.pomFilePath, 'utf8');
145
+ const lines = source.split(/\r?\n/);
146
+ const center = correlated.context.failedAction.line ?? 1;
147
+ const start = Math.max(0, center - 8);
148
+ const end = Math.min(lines.length, center + 8);
149
+ sourceContext.push({
150
+ filePath: path.relative(workspaceRoot, sourceMapping.pomFilePath),
151
+ startLine: start + 1,
152
+ endLine: end,
153
+ content: lines.slice(start, end).join('\n'),
154
+ });
155
+ } catch {
156
+ // Source mapping remains available as an action observation even when a snippet cannot be read.
157
+ }
158
+ }
159
+ const bundle = buildEvidenceBundle({
160
+ executionId: input.executionId ?? `trace-${Date.now()}`,
161
+ testIdentity: input.testIdentity ?? context.failedAction.sourceFile ?? 'unknown-test',
162
+ context,
163
+ failureCategory: correlated.classification.category,
164
+ redactionComplete: true,
165
+ sourceContext,
166
+ artifacts: [
167
+ { kind: 'trace', reference: path.relative(workspaceRoot, tracePath), redacted: true },
168
+ ...(networkEntryName ? [{ kind: 'network' as const, reference: path.relative(workspaceRoot, networkEntryName), redacted: true }] : []),
169
+ ],
170
+ });
171
+ const agent = await runRepairProposalAgent({
172
+ context,
173
+ bundle,
174
+ provider: input.provider ?? configuredProvider(),
175
+ allowModelEscalation: true,
176
+ strategy: correlated.classification.category === 'LOCATOR_DRIFT'
177
+ && correlated.classification.confidence >= 0.85
178
+ && Boolean(deterministicProposedLocator)
179
+ ? 'single-shot'
180
+ : 'agent',
181
+ maxDurationMs: (() => {
182
+ const raw = Number(process.env.PIE_LLM_AGENT_MAX_DURATION_MS ?? 180000);
183
+ return Number.isFinite(raw) && raw > 0 ? raw : 180000;
184
+ })(),
185
+ // Step budget prevents deadlocks; token limits remain provider/user controlled.
186
+ maxSteps: 6,
187
+ actionHandlers: {
188
+ inspect_evidence: async () => ({
189
+ category: correlated.classification.category,
190
+ failedAction: correlated.context.failedAction,
191
+ evidenceCompleteness: correlated.context.evidenceCompleteness,
192
+ networkEvents: correlated.context.networkEvents.length,
193
+ consoleEvents: correlated.context.consoleEvents.length,
194
+ }),
195
+ inspect_browser_state: async () => {
196
+ if (input.enableBrowserInvestigation !== true) {
197
+ return { status: 'DISABLED', reason: 'Browser investigation requires explicit opt-in.' };
198
+ }
199
+ if (!input.browserUrl) {
200
+ return { status: 'INSUFFICIENT_EVIDENCE', reason: 'No explicit browser URL was supplied.' };
201
+ }
202
+ let browserHost: string;
203
+ try {
204
+ browserHost = new URL(input.browserUrl).hostname;
205
+ } catch {
206
+ return { status: 'INSUFFICIENT_EVIDENCE', reason: 'The supplied browser URL is invalid.' };
207
+ }
208
+ if (!input.browserAllowedHosts?.includes(browserHost)) {
209
+ return { status: 'POLICY_BLOCKED', reason: 'Browser investigation requires an explicit allowed-host list.' };
210
+ }
211
+ const investigation = await DirectBrowserInvestigator.investigateUrl({
212
+ url: input.browserUrl,
213
+ executionId: `${input.executionId ?? 'trace'}-browser-investigation`,
214
+ timeoutMs: 10000,
215
+ });
216
+ const clip = (value: unknown, limit: number): string | undefined => {
217
+ const text = typeof value === 'string' ? value : value === undefined ? undefined : JSON.stringify(value);
218
+ if (text === undefined || text.length <= limit) return text;
219
+ return `${text.slice(0, limit)}\n[PIE browser evidence clipped]`;
220
+ };
221
+ return {
222
+ status: investigation.status,
223
+ pageUrl: investigation.pageUrl,
224
+ error: investigation.error,
225
+ domSnapshot: clip(investigation.domSnapshotRecord?.payload, 8000),
226
+ ariaSnapshot: clip(investigation.ariaSnapshotRecord?.payload, 8000),
227
+ recordKinds: investigation.records.map((record) => record.evidenceType).slice(0, 20),
228
+ };
229
+ },
230
+ inspect_repository: async () => ({
231
+ repository: intelligence.profile?.repository,
232
+ structure: intelligence.profile?.structure,
233
+ paths: intelligence.profile?.paths,
234
+ locatorConventions: intelligence.profile?.locatorConventions,
235
+ testConventions: intelligence.profile?.testConventions,
236
+ domainTerms: intelligence.profile?.domainTerms?.slice(0, 50),
237
+ }),
238
+ read_source_file: async (action) => {
239
+ const sourcePath = action.path ?? action.sourceFile;
240
+ if (!sourcePath) return { status: 'INPUT_REQUIRED', reason: 'A path or sourceFile is required.' };
241
+ const resolved = assertWorkspacePath(workspaceRoot, sourcePath, 'Source file');
242
+ const content = await fs.readFile(resolved, 'utf8');
243
+ const clipped = content.length > 16000 ? `${content.slice(0, 16000)}\n[PIE source evidence clipped]` : content;
244
+ return { status: 'FOUND', filePath: path.relative(workspaceRoot, resolved), content: EvidenceRedactor.redactText(clipped).redactedText };
245
+ },
246
+ search_repository: async (action) => {
247
+ if (!action.query) return { status: 'INPUT_REQUIRED', reason: 'A query is required.' };
248
+ return { status: 'FOUND', query: action.query, matches: await searchRepository(workspaceRoot, action.query) };
249
+ },
250
+ discover_source_mapping: async () => sourceMapping ?? {
251
+ status: 'NOT_FOUND',
252
+ reason: 'No unique source mapping was discovered.',
253
+ },
254
+ rank_locator_candidates: async () => ({
255
+ ...(() => {
256
+ const domRoot = (correlated.context as unknown as { domRoot?: unknown }).domRoot;
257
+ if (!domRoot) return { status: 'NO_DOM_EVIDENCE', candidates: [], proposedLocator: null };
258
+ try {
259
+ const candidates = CandidateExtractor.extractCandidates(domRoot as Parameters<typeof CandidateExtractor.extractCandidates>[0], correlated.context.failedAction);
260
+ const ranked = RepairCandidateRanker.rank(
261
+ candidates,
262
+ correlated.context.failedAction.selector,
263
+ correlated.context.failedAction.action,
264
+ intelligence,
265
+ domRoot as Parameters<typeof CandidateExtractor.extractCandidates>[0],
266
+ correlated.context.failedAction.selector
267
+ );
268
+ const decision = AbstentionPolicy.evaluate(ranked);
269
+ return {
270
+ status: decision.shouldAbstain ? 'CANDIDATES_REQUIRE_REVIEW' : 'CANDIDATE_AVAILABLE',
271
+ proposedLocator: deterministicProposedLocator ?? null,
272
+ abstentionStage: decision.stage,
273
+ abstentionReason: decision.reason ?? null,
274
+ candidates: ranked.slice(0, 10).map((candidate) => ({
275
+ locator: candidate.locatorExpression,
276
+ score: candidate.breakdown.score,
277
+ identityMatch: candidate.breakdown.identityMatch,
278
+ matchCount: candidate.breakdown.matchCount,
279
+ element: {
280
+ tag: candidate.element.tag,
281
+ role: candidate.element.role,
282
+ accessibleName: candidate.element.accessibleName,
283
+ text: candidate.element.text,
284
+ attributes: candidate.element.attributes,
285
+ },
286
+ })),
287
+ };
288
+ } catch (error) {
289
+ return { status: 'CANDIDATE_EXTRACTION_FAILED', candidates: [], proposedLocator: deterministicProposedLocator ?? null, reason: error instanceof Error ? error.message : String(error) };
290
+ }
291
+ })(),
292
+ }),
293
+ build_repair_proposal: async (action) => ({
294
+ status: 'PROPOSAL_ONLY',
295
+ target: action.target ?? null,
296
+ locator: action.locator ?? deterministicProposedLocator ?? null,
297
+ message: 'PIE has not modified or executed any source. The model must return the final schema-validated proposal.',
298
+ }),
299
+ run_target_test: async (action) => {
300
+ if (input.enableTestExecution !== true) return { status: 'DISABLED', reason: 'Targeted test execution requires explicit opt-in.' };
301
+ const target = action.testFile ?? action.sourceFile;
302
+ if (!target) return { status: 'INPUT_REQUIRED', reason: 'testFile or sourceFile is required.' };
303
+ const testPath = assertWorkspacePath(workspaceRoot, target, 'Target test');
304
+ const relativeTest = path.relative(workspaceRoot, testPath);
305
+ const args = ['playwright', 'test', relativeTest, '--reporter=line'];
306
+ if (action.configPath) args.push('--config', path.relative(workspaceRoot, assertWorkspacePath(workspaceRoot, action.configPath, 'Playwright config')));
307
+ const execution = await ExecutionRunner.run('npx', { cwd: workspaceRoot, args, timeoutMs: 120000 });
308
+ const clip = (value: string): string => EvidenceRedactor.redactText(value.slice(0, 8000)).redactedText;
309
+ return { status: execution.exitCode === 0 ? 'PASSED' : 'FAILED', exitCode: execution.exitCode, timedOut: execution.timedOut, stdout: clip(execution.stdout), stderr: clip(execution.stderr), durationMs: execution.durationMs };
310
+ },
311
+ verify_repair: async () => ({
312
+ status: 'NOT_EXECUTED',
313
+ reason: 'Trace proposal workflow is proposal-only. Isolated verification requires the repair workflow and explicit execution policy.',
314
+ }),
315
+ },
316
+ });
317
+ return { context, correlated, bundle, agent };
318
+ }
@@ -0,0 +1,48 @@
1
+ import { LlmRepairProposal, parseLlmRepairProposal } from './llm-proposal.js';
2
+ import { RepairWorkflowInput, RepairWorkflowResult, runRepairWorkflow } from '../repair/repair-workflow.js';
3
+ import { WorkflowPlan, compileWorkflowPlan } from '../repair/workflow-plan.js';
4
+
5
+ export interface VerifiedLlmRepairInput extends Omit<RepairWorkflowInput, 'operation'> {
6
+ proposal: LlmRepairProposal | unknown;
7
+ }
8
+
9
+ export interface LlmRepairPlanValidation {
10
+ isValid: boolean;
11
+ proposal?: LlmRepairProposal | undefined;
12
+ workflowPlan?: WorkflowPlan | undefined;
13
+ errors: string[];
14
+ }
15
+
16
+ /** Validates a possibly multi-operation LLM plan without touching source files. */
17
+ export function validateLlmRepairPlan(input: unknown): LlmRepairPlanValidation {
18
+ const parsed = parseLlmRepairProposal(input);
19
+ if (!parsed.isValid || !parsed.proposal) return { isValid: false, errors: parsed.errors };
20
+ const workflowPlan = compileWorkflowPlan(parsed.proposal.operations);
21
+ if (workflowPlan.status !== 'EXECUTABLE') return { isValid: false, proposal: parsed.proposal, workflowPlan, errors: workflowPlan.errors };
22
+ return { isValid: true, proposal: parsed.proposal, workflowPlan, errors: [] };
23
+ }
24
+
25
+ /**
26
+ * Bridges a validated LLM proposal into PIE's existing deterministic repair
27
+ * workflow. The bridge is intentionally limited to one exact-target operation
28
+ * until multi-operation convergence has its own combined verification proof.
29
+ */
30
+ export async function runVerifiedLlmRepairWorkflow(input: VerifiedLlmRepairInput): Promise<RepairWorkflowResult> {
31
+ const parsed = parseLlmRepairProposal(input.proposal);
32
+ if (!parsed.isValid || !parsed.proposal) {
33
+ throw new Error(`LLM repair proposal rejected: ${parsed.errors.join('; ')}`);
34
+ }
35
+ if (parsed.proposal.decision === 'ABSTAIN') {
36
+ throw new Error('LLM repair proposal requested abstention');
37
+ }
38
+ if (parsed.proposal.operations.length !== 1) {
39
+ throw new Error('LLM repair proposal requires exactly one operation for verified execution');
40
+ }
41
+ const operation = parsed.proposal.operations[0]!;
42
+ if (operation.kind === 'abstain') throw new Error('LLM repair proposal cannot execute an abstain operation');
43
+ return runRepairWorkflow({
44
+ ...input,
45
+ operation,
46
+ requireOperationTargetMatch: true,
47
+ });
48
+ }