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,761 @@
1
+ import { Project, Node } from 'ts-morph';
2
+ import { AssertionHasher, CompositeIntentFingerprint } from './assertion-hasher.js';
3
+ import { DiffAllowlistValidator, StatementDiffAllowlistValidator } from './diff-allowlist.js';
4
+ import {
5
+ AssertionTamperedError,
6
+ IntentInvariantViolationError,
7
+ UnauthorizedAstModificationError,
8
+ } from '../core/errors/engine-errors.js';
9
+ import { ResolvedElement } from '../trace/snapshot-resolver.js';
10
+
11
+ export interface ValidationTarget {
12
+ testFilePath: string;
13
+ originalFingerprint: string;
14
+ candidateElement: ResolvedElement;
15
+ intendedAction: string; // e.g. "click", "fill"
16
+ originalSelector?: string | undefined;
17
+ businessOracleStatus?: 'verified' | 'contradicted' | 'unavailable' | undefined;
18
+ }
19
+
20
+ export interface VerifiedExecutionProof {
21
+ proposalId?: string | undefined;
22
+ worktreeId: string;
23
+ repositoryIdentity?: string | undefined;
24
+ originalSourceHash?: string | undefined;
25
+ modifiedSourceHash?: string | undefined;
26
+ diffHash?: string | undefined;
27
+ targetTestIdentity?: string | undefined;
28
+ testFilePath: string;
29
+ command: string;
30
+ exitCode: number;
31
+ stdout: string;
32
+ stderr: string;
33
+ passed: boolean;
34
+ executionOutcome?: 'PASS' | 'FAIL' | undefined;
35
+ durationMs: number;
36
+ targetTestEvidence?: string[] | undefined;
37
+ regressionEvidence?: string[] | undefined;
38
+ assertionIntegrityValid?: boolean | undefined;
39
+ timestamp: number;
40
+ proofVersion?: string | undefined;
41
+ }
42
+
43
+ export interface PreflightProposalTarget {
44
+ testFilePath: string;
45
+ originalCompositeFingerprint: CompositeIntentFingerprint;
46
+ candidateElement: ResolvedElement;
47
+ intendedAction: string;
48
+ originalSelector?: string | undefined;
49
+ businessOracleStatus?: 'verified' | 'contradicted' | 'unavailable' | undefined;
50
+ }
51
+
52
+ export interface PreflightProposalResult {
53
+ isValid: boolean;
54
+ assertionsPreserved: boolean; // A
55
+ testBodyPreserved: boolean; // T
56
+ fixturesPreserved: boolean; // F
57
+ identityAndActionPreserved: boolean; // I
58
+ summary: string;
59
+ reason?: string | undefined;
60
+ }
61
+
62
+ export interface VerifiedAuthorizationTarget {
63
+ testFilePath: string;
64
+ originalCompositeFingerprint: CompositeIntentFingerprint;
65
+ pageObjectOriginalSource: string;
66
+ pageObjectPatchedSource: string;
67
+ pageObjectClassName: string;
68
+ targetMemberName: string;
69
+ candidateElement: ResolvedElement;
70
+ intendedAction: string;
71
+ originalSelector?: string | undefined;
72
+ executionProof: VerifiedExecutionProof;
73
+ businessOracleStatus?: 'verified' | 'contradicted' | 'unavailable' | undefined;
74
+ }
75
+
76
+ export interface VerifiedAuthorizationResult {
77
+ isAuthorized: boolean;
78
+ assertionsPreserved: boolean; // A
79
+ testBodyPreserved: boolean; // T
80
+ fixturesPreserved: boolean; // F
81
+ identityAndActionPreserved: boolean; // I
82
+ diffAllowlistPassed: boolean; // D
83
+ executionVerified: boolean; // E
84
+ summary: string;
85
+ reason?: string | undefined;
86
+ }
87
+
88
+ export interface IntentV2ValidationTarget {
89
+ testFilePath: string;
90
+ originalCompositeFingerprint: CompositeIntentFingerprint;
91
+ pageObjectOriginalSource?: string | undefined;
92
+ pageObjectPatchedSource?: string | undefined;
93
+ pageObjectClassName?: string | undefined;
94
+ targetMemberName?: string | undefined;
95
+ candidateElement: ResolvedElement;
96
+ intendedAction: string;
97
+ originalSelector?: string | undefined;
98
+ executionPassed?: boolean | undefined;
99
+ executionProof?: VerifiedExecutionProof | undefined;
100
+ mode?: 'pre-flight' | 'authorization' | undefined;
101
+ strict?: boolean | undefined;
102
+ businessOracleStatus?: 'verified' | 'contradicted' | 'unavailable' | undefined;
103
+ pattern?: string | undefined;
104
+ }
105
+
106
+ export interface IntentValidationResult {
107
+ isValid: boolean;
108
+ assertionPreserved: boolean;
109
+ actionSemanticsValid: boolean;
110
+ identityPreserved: boolean;
111
+ reason?: string | undefined;
112
+ }
113
+
114
+ export interface IntentV2ValidationResult {
115
+ isValid: boolean;
116
+ assertionsPreserved: boolean; // A
117
+ testBodyPreserved: boolean; // T
118
+ fixturesPreserved: boolean; // F
119
+ identityAndActionPreserved: boolean; // I
120
+ diffAllowlistPassed: boolean; // D
121
+ executionVerified: boolean; // E
122
+ reason?: string | undefined;
123
+ summary: string;
124
+ }
125
+
126
+ export class IntentValidator {
127
+ private static readonly CONFLICTING_ACTION_PAIRS = [
128
+ {
129
+ positive: ['submit', 'login', 'checkout', 'save', 'confirm', 'proceed', 'pay', 'order', 'continue', 'apply'],
130
+ negative: ['cancel', 'close', 'reset', 'abort', 'back', 'dismiss', 'exit'],
131
+ },
132
+ {
133
+ positive: ['create', 'add', 'insert', 'new', 'edit', 'update', 'modify'],
134
+ negative: ['delete', 'remove', 'destroy', 'clear', 'purge'],
135
+ },
136
+ ];
137
+
138
+ /**
139
+ * Validates whether candidate element preserves genuine business identity
140
+ * without substituting contradictory actions (e.g. replacing 'Submit' with 'Cancel').
141
+ */
142
+ public static verifyTargetIdentity(
143
+ originalSelector: string | undefined,
144
+ candidate: ResolvedElement
145
+ ): { isPreserved: boolean; reason?: string } {
146
+ if (!originalSelector) {
147
+ return { isPreserved: true };
148
+ }
149
+
150
+ const origTokens = originalSelector.toLowerCase().replace(/[^a-z0-9]/g, ' ').split(/\s+/).filter(Boolean);
151
+ const candidateText = [
152
+ candidate.accessibleName ?? '',
153
+ candidate.text ?? '',
154
+ candidate.attributes['data-testid'] ?? '',
155
+ candidate.attributes['aria-label'] ?? '',
156
+ candidate.attributes['id'] ?? '',
157
+ ].join(' ').toLowerCase();
158
+ const candidateTokens = candidateText.replace(/[^a-z0-9]/g, ' ').split(/\s+/).filter(Boolean);
159
+
160
+ // Hard Conflict Check: Reject substituting positive action with negative/cancellation action
161
+ for (const pair of IntentValidator.CONFLICTING_ACTION_PAIRS) {
162
+ const origHasPositive = pair.positive.some((p) => origTokens.includes(p));
163
+ const candHasNegative = pair.negative.some((n) => candidateTokens.includes(n));
164
+ if (origHasPositive && candHasNegative) {
165
+ return {
166
+ isPreserved: false,
167
+ reason: `Identity violation: Target '${originalSelector}' appears to be a confirmation/submission action, but replacement candidate '${candidate.accessibleName ?? candidate.tag}' has contradictory cancellation semantics.`,
168
+ };
169
+ }
170
+
171
+ const origHasNegative = pair.negative.some((n) => origTokens.includes(n));
172
+ const candHasPositive = pair.positive.some((p) => candidateTokens.includes(p));
173
+ if (origHasNegative && candHasPositive) {
174
+ return {
175
+ isPreserved: false,
176
+ reason: `Identity violation: Target '${originalSelector}' appears to be a cancellation action, but replacement candidate '${candidate.accessibleName ?? candidate.tag}' has contradictory submission semantics.`,
177
+ };
178
+ }
179
+ }
180
+
181
+ // Destructive Action Invariant: A deletion/removal action must never be substituted by a non-destructive element
182
+ const isDestructiveOriginal = ['delete', 'remove', 'destroy', 'purge'].some((t) => origTokens.includes(t));
183
+ const isDestructiveCandidate = ['delete', 'remove', 'destroy', 'purge'].some((t) => candidateTokens.includes(t));
184
+ if (isDestructiveOriginal && !isDestructiveCandidate) {
185
+ return {
186
+ isPreserved: false,
187
+ reason: `Identity violation: Target '${originalSelector}' is a destructive action, but candidate '${candidate.accessibleName ?? candidate.tag}' lacks deletion/removal semantics.`,
188
+ };
189
+ }
190
+
191
+ return { isPreserved: true };
192
+ }
193
+
194
+ /**
195
+ * Backward-compatible validation for simple assertion and identity checks.
196
+ */
197
+ public static validate(target: ValidationTarget): IntentValidationResult {
198
+ const postPatchFingerprint = AssertionHasher.computeFingerprint(target.testFilePath);
199
+ if (postPatchFingerprint !== target.originalFingerprint) {
200
+ throw new AssertionTamperedError(target.originalFingerprint, postPatchFingerprint);
201
+ }
202
+
203
+ const actionSemanticsValid = IntentValidator.checkActionSemantics(target.intendedAction, target.candidateElement);
204
+ const identityCheck = IntentValidator.verifyTargetIdentity(target.originalSelector, target.candidateElement);
205
+
206
+ return {
207
+ isValid: actionSemanticsValid && identityCheck.isPreserved,
208
+ assertionPreserved: true,
209
+ actionSemanticsValid,
210
+ identityPreserved: identityCheck.isPreserved,
211
+ reason: identityCheck.reason,
212
+ };
213
+ }
214
+
215
+ /**
216
+ * Evaluates proposal pre-flight invariant: V_pre = A ∧ T ∧ F ∧ I
217
+ * Used strictly for in-memory planning without claiming mutation authorization.
218
+ */
219
+ public static validateProposal(target: PreflightProposalTarget): PreflightProposalResult {
220
+ const postPatch = AssertionHasher.computeCompositeFingerprint(target.testFilePath);
221
+
222
+ const assertionsPreserved =
223
+ postPatch.assertionFingerprint === target.originalCompositeFingerprint.assertionFingerprint;
224
+ if (!assertionsPreserved) {
225
+ throw new AssertionTamperedError(
226
+ target.originalCompositeFingerprint.assertionFingerprint,
227
+ postPatch.assertionFingerprint
228
+ );
229
+ }
230
+
231
+ const testBodyPreserved =
232
+ postPatch.testBodyFingerprint === target.originalCompositeFingerprint.testBodyFingerprint;
233
+ if (!testBodyPreserved) {
234
+ throw new IntentInvariantViolationError(
235
+ 'TestBodyStructure',
236
+ 'Test statement order, control flow, conditions, or test body AST nodes were modified.'
237
+ );
238
+ }
239
+
240
+ const fixturesPreserved =
241
+ postPatch.fixtureFingerprint === target.originalCompositeFingerprint.fixtureFingerprint;
242
+ if (!fixturesPreserved) {
243
+ throw new IntentInvariantViolationError(
244
+ 'FixtureParameters',
245
+ 'Test fixtures, input parameters, or literal values were altered or reordered.'
246
+ );
247
+ }
248
+
249
+ const identityCheck = IntentValidator.verifyTargetIdentity(target.originalSelector, target.candidateElement);
250
+ const actionSemanticsValid = IntentValidator.checkActionSemantics(target.intendedAction, target.candidateElement);
251
+ const identityAndActionPreserved = actionSemanticsValid && identityCheck.isPreserved;
252
+
253
+ if (target.businessOracleStatus === 'contradicted') {
254
+ return {
255
+ isValid: false,
256
+ assertionsPreserved,
257
+ testBodyPreserved,
258
+ fixturesPreserved,
259
+ identityAndActionPreserved: false,
260
+ summary: 'Rejected: Independent business oracle contradicted target identity',
261
+ reason: 'Business oracle contradicted the candidate identity',
262
+ };
263
+ }
264
+
265
+ const isValid = assertionsPreserved && testBodyPreserved && fixturesPreserved && identityAndActionPreserved;
266
+
267
+ return {
268
+ isValid,
269
+ assertionsPreserved,
270
+ testBodyPreserved,
271
+ fixturesPreserved,
272
+ identityAndActionPreserved,
273
+ summary: isValid
274
+ ? 'Pre-flight Intent Invariant passed: V_pre = A ∧ T ∧ F ∧ I'
275
+ : `Pre-flight Intent Invariant failed: ${identityCheck.reason ?? 'Action semantics invalid'}`,
276
+ reason: identityCheck.reason,
277
+ };
278
+ }
279
+
280
+ /**
281
+ * Evaluates strict production authorization invariant: V = A ∧ T ∧ F ∧ I ∧ D ∧ E
282
+ * Unconditionally fails closed if any evidence is missing or execution proof fails.
283
+ */
284
+ public static authorizeVerifiedRepair(target: VerifiedAuthorizationTarget): VerifiedAuthorizationResult {
285
+ const preflight = IntentValidator.validateProposal({
286
+ testFilePath: target.testFilePath,
287
+ originalCompositeFingerprint: target.originalCompositeFingerprint,
288
+ candidateElement: target.candidateElement,
289
+ intendedAction: target.intendedAction,
290
+ originalSelector: target.originalSelector,
291
+ businessOracleStatus: target.businessOracleStatus,
292
+ });
293
+
294
+ if (!preflight.isValid) {
295
+ return {
296
+ isAuthorized: false,
297
+ assertionsPreserved: preflight.assertionsPreserved,
298
+ testBodyPreserved: preflight.testBodyPreserved,
299
+ fixturesPreserved: preflight.fixturesPreserved,
300
+ identityAndActionPreserved: preflight.identityAndActionPreserved,
301
+ diffAllowlistPassed: false,
302
+ executionVerified: false,
303
+ summary: `Authorization Rejected: Pre-flight clauses failed (${preflight.summary})`,
304
+ reason: preflight.reason,
305
+ };
306
+ }
307
+
308
+ // 5. D: Diff Allowlist
309
+ const diffResult = DiffAllowlistValidator.validate({
310
+ originalSource: target.pageObjectOriginalSource,
311
+ patchedSource: target.pageObjectPatchedSource,
312
+ targetClassName: target.pageObjectClassName,
313
+ targetMemberName: target.targetMemberName,
314
+ });
315
+
316
+ if (!diffResult.isAllowed) {
317
+ throw new UnauthorizedAstModificationError(diffResult.reason ?? 'Unknown violation');
318
+ }
319
+
320
+ // 6. E: Execution Verification
321
+ const proof = target.executionProof;
322
+ if (!proof || !proof.passed || proof.exitCode !== 0) {
323
+ return {
324
+ isAuthorized: false,
325
+ assertionsPreserved: preflight.assertionsPreserved,
326
+ testBodyPreserved: preflight.testBodyPreserved,
327
+ fixturesPreserved: preflight.fixturesPreserved,
328
+ identityAndActionPreserved: preflight.identityAndActionPreserved,
329
+ diffAllowlistPassed: true,
330
+ executionVerified: false,
331
+ summary: `Authorization Rejected: Target test execution did not pass (exitCode=${proof?.exitCode ?? 'missing'})`,
332
+ reason: 'Worktree test execution failed or execution proof was missing',
333
+ };
334
+ }
335
+
336
+ return {
337
+ isAuthorized: true,
338
+ assertionsPreserved: true,
339
+ testBodyPreserved: true,
340
+ fixturesPreserved: true,
341
+ identityAndActionPreserved: true,
342
+ diffAllowlistPassed: true,
343
+ executionVerified: true,
344
+ summary: 'Intent Invariant v2 satisfied: V = A ∧ T ∧ F ∧ I ∧ D ∧ E (Authorized for workspace promotion)',
345
+ };
346
+ }
347
+
348
+ /**
349
+ * INVARIANT: Input Data Integrity.
350
+ * Tests are executable business specifications. Repairing a broken locator or timing
351
+ * issue MUST NOT mutate business input parameters (quantities, credentials, search queries, prices).
352
+ */
353
+ public static validateInputDataIntegrity(
354
+ originalSource: string,
355
+ patchedSource: string
356
+ ): { isValid: boolean; reason?: string } {
357
+ const extractInputs = (source: string): Array<{ action: string; arg: string }> => {
358
+ const inputs: Array<{ action: string; arg: string }> = [];
359
+ const project = new Project({ useInMemoryFileSystem: true });
360
+ const sourceFile = project.createSourceFile('temp.spec.ts', source, { overwrite: true });
361
+
362
+ sourceFile.forEachDescendant((node) => {
363
+ if (Node.isCallExpression(node)) {
364
+ const expr = node.getExpression();
365
+ if (Node.isPropertyAccessExpression(expr)) {
366
+ const actionName = expr.getName();
367
+ if (actionName === 'fill' || actionName === 'type' || actionName === 'selectOption') {
368
+ const firstArg = node.getArguments()[0];
369
+ if (firstArg) {
370
+ let argText = firstArg.getText().trim();
371
+ if (Node.isStringLiteral(firstArg)) {
372
+ argText = firstArg.getLiteralValue();
373
+ } else if (
374
+ (argText.startsWith("'") && argText.endsWith("'")) ||
375
+ (argText.startsWith('"') && argText.endsWith('"')) ||
376
+ (argText.startsWith('`') && argText.endsWith('`'))
377
+ ) {
378
+ argText = argText.slice(1, -1);
379
+ }
380
+ inputs.push({ action: actionName, arg: argText });
381
+ }
382
+ }
383
+ }
384
+ }
385
+ });
386
+ return inputs;
387
+ };
388
+
389
+ const origInputs = extractInputs(originalSource);
390
+ const patchedInputs = extractInputs(patchedSource);
391
+
392
+ if (origInputs.length !== patchedInputs.length) {
393
+ return {
394
+ isValid: false,
395
+ reason: `Input data invariant violated: Input action count changed from ${origInputs.length} to ${patchedInputs.length}. Test inputs cannot be added or removed.`,
396
+ };
397
+ }
398
+
399
+ for (let i = 0; i < origInputs.length; i++) {
400
+ if (origInputs[i]!.action !== patchedInputs[i]!.action) {
401
+ return {
402
+ isValid: false,
403
+ reason: `Input data invariant violated: Input action type changed at index ${i} from '${origInputs[i]!.action}' to '${patchedInputs[i]!.action}'.`,
404
+ };
405
+ }
406
+ if (origInputs[i]!.arg !== patchedInputs[i]!.arg) {
407
+ return {
408
+ isValid: false,
409
+ reason: `Input data invariant violated: Action payload mutated from '${origInputs[i]!.arg}' to '${patchedInputs[i]!.arg}'. Test inputs cannot be altered to force a pass.`,
410
+ };
411
+ }
412
+ }
413
+
414
+ return { isValid: true };
415
+ }
416
+
417
+ /**
418
+ * INVARIANT: Workflow Step Integrity.
419
+ * Repairs must not delete, add, or reorder intermediate workflow steps (e.g. swapping or skipping checkout steps).
420
+ */
421
+ public static validateWorkflowStepIntegrity(
422
+ originalSource: string,
423
+ patchedSource: string
424
+ ): { isValid: boolean; reason?: string } {
425
+ const extractActionSequence = (source: string): string[] => {
426
+ const actions: string[] = [];
427
+ const project = new Project({ useInMemoryFileSystem: true });
428
+ const sourceFile = project.createSourceFile('temp.spec.ts', source, { overwrite: true });
429
+ const approvedActions = new Set([
430
+ 'click',
431
+ 'fill',
432
+ 'type',
433
+ 'selectOption',
434
+ 'check',
435
+ 'uncheck',
436
+ 'press',
437
+ 'goto',
438
+ 'dblclick',
439
+ 'hover',
440
+ 'focus',
441
+ ]);
442
+
443
+ sourceFile.forEachDescendant((node) => {
444
+ if (Node.isCallExpression(node)) {
445
+ const expr = node.getExpression();
446
+ if (Node.isPropertyAccessExpression(expr)) {
447
+ const actionName = expr.getName();
448
+ if (approvedActions.has(actionName)) {
449
+ actions.push(actionName);
450
+ }
451
+ }
452
+ }
453
+ });
454
+ return actions;
455
+ };
456
+
457
+ const origActions = extractActionSequence(originalSource);
458
+ const patchedActions = extractActionSequence(patchedSource);
459
+
460
+ if (origActions.length !== patchedActions.length) {
461
+ return {
462
+ isValid: false,
463
+ reason: `Workflow sequence invariant violated: Test step count changed from ${origActions.length} to ${patchedActions.length}. Repair cannot delete, add, or bypass intermediate test steps.`,
464
+ };
465
+ }
466
+
467
+ for (let i = 0; i < origActions.length; i++) {
468
+ if (origActions[i] !== patchedActions[i]) {
469
+ return {
470
+ isValid: false,
471
+ reason: `Workflow sequence invariant violated: Action sequence altered at step ${i + 1} (expected '${origActions[i]}', found '${patchedActions[i]}'). Test action order must be preserved.`,
472
+ };
473
+ }
474
+ }
475
+
476
+ return { isValid: true };
477
+ }
478
+
479
+ /**
480
+ * Unified v2 entry point. Preserves backward compatibility while enforcing fail-closed
481
+ * authorization when mode !== 'pre-flight'.
482
+ */
483
+ public static validateV2(target: IntentV2ValidationTarget): IntentV2ValidationResult {
484
+ if (!target.originalCompositeFingerprint) {
485
+ return {
486
+ isValid: false,
487
+ assertionsPreserved: false,
488
+ testBodyPreserved: false,
489
+ fixturesPreserved: false,
490
+ identityAndActionPreserved: false,
491
+ diffAllowlistPassed: false,
492
+ executionVerified: false,
493
+ reason: 'Missing original composite fingerprint',
494
+ summary: 'Rejected: Baseline composite fingerprint was not provided',
495
+ };
496
+ }
497
+
498
+ const isPreflight = target.mode === 'pre-flight';
499
+
500
+ // Branch 1: Dedicated validation for statement-level repairs (where test specification is directly patched)
501
+ if (target.pattern === 'statement-patch') {
502
+ const origSource = target.pageObjectOriginalSource ?? '';
503
+ const patchedSource = target.pageObjectPatchedSource ?? '';
504
+
505
+ // 1. Assertions Invariant: All original assertions must remain strictly intact
506
+ const origAssertions = AssertionHasher.extractAssertionRecordsFromSource(origSource);
507
+ const postAssertions = AssertionHasher.extractAssertionRecordsFromSource(patchedSource);
508
+ const postSet = new Set(postAssertions.map((a) => JSON.stringify(a)));
509
+ const assertionsPreserved = origAssertions.every((a) => postSet.has(JSON.stringify(a)));
510
+
511
+ if (!assertionsPreserved) {
512
+ throw new AssertionTamperedError(
513
+ JSON.stringify(origAssertions),
514
+ JSON.stringify(postAssertions)
515
+ );
516
+ }
517
+
518
+ // 2. Input data invariant
519
+ const inputCheck = IntentValidator.validateInputDataIntegrity(origSource, patchedSource);
520
+ if (!inputCheck.isValid) {
521
+ return {
522
+ isValid: false,
523
+ assertionsPreserved: true,
524
+ testBodyPreserved: false,
525
+ fixturesPreserved: false,
526
+ identityAndActionPreserved: false,
527
+ diffAllowlistPassed: false,
528
+ executionVerified: false,
529
+ reason: inputCheck.reason,
530
+ summary: `Rejected: ${inputCheck.reason}`,
531
+ };
532
+ }
533
+
534
+ // 3. Workflow step integrity
535
+ const workflowCheck = IntentValidator.validateWorkflowStepIntegrity(origSource, patchedSource);
536
+ if (!workflowCheck.isValid) {
537
+ return {
538
+ isValid: false,
539
+ assertionsPreserved: true,
540
+ testBodyPreserved: false,
541
+ fixturesPreserved: false,
542
+ identityAndActionPreserved: false,
543
+ diffAllowlistPassed: false,
544
+ executionVerified: false,
545
+ reason: workflowCheck.reason,
546
+ summary: `Rejected: ${workflowCheck.reason}`,
547
+ };
548
+ }
549
+
550
+ // 4. Statement Diff Allowlist
551
+ const diffResult = StatementDiffAllowlistValidator.validate({
552
+ originalSource: origSource,
553
+ patchedSource: patchedSource,
554
+ });
555
+
556
+ if (!diffResult.isAllowed) {
557
+ throw new UnauthorizedAstModificationError(diffResult.reason ?? 'Unknown violation');
558
+ }
559
+
560
+ // 5. Target identity & business oracle
561
+ const identityCheck = IntentValidator.verifyTargetIdentity(target.originalSelector, target.candidateElement);
562
+ if (target.businessOracleStatus === 'contradicted') {
563
+ return {
564
+ isValid: false,
565
+ assertionsPreserved: true,
566
+ testBodyPreserved: true,
567
+ fixturesPreserved: true,
568
+ identityAndActionPreserved: false,
569
+ diffAllowlistPassed: true,
570
+ executionVerified: false,
571
+ reason: 'Business oracle contradicted the candidate identity',
572
+ summary: 'Rejected: Independent business oracle contradicted target identity',
573
+ };
574
+ }
575
+
576
+ // 6. Execution Verification
577
+ let executionVerified = false;
578
+ if (
579
+ target.executionProof &&
580
+ target.executionProof.passed === true &&
581
+ target.executionProof.exitCode === 0 &&
582
+ (target.executionProof.executionOutcome === 'PASS' || target.executionProof.executionOutcome === undefined) &&
583
+ target.executionProof.assertionIntegrityValid !== false
584
+ ) {
585
+ executionVerified = true;
586
+ }
587
+
588
+ const isValid = isPreflight
589
+ ? assertionsPreserved && inputCheck.isValid && workflowCheck.isValid && diffResult.isAllowed && identityCheck.isPreserved
590
+ : assertionsPreserved && inputCheck.isValid && workflowCheck.isValid && diffResult.isAllowed && identityCheck.isPreserved && executionVerified;
591
+
592
+ return {
593
+ isValid,
594
+ assertionsPreserved: true,
595
+ testBodyPreserved: true,
596
+ fixturesPreserved: true,
597
+ identityAndActionPreserved: identityCheck.isPreserved,
598
+ diffAllowlistPassed: diffResult.isAllowed,
599
+ executionVerified,
600
+ reason: identityCheck.reason,
601
+ summary: isValid
602
+ ? isPreflight
603
+ ? 'Pre-flight Statement Repair Invariant passed: V_stmt_pre = A_pres ∧ I_data ∧ W_step ∧ D_stmt'
604
+ : 'Statement Repair Intent Invariant v2 satisfied: V_stmt = A_pres ∧ I_data ∧ W_step ∧ D_stmt ∧ E (Strict intent preservation proved)'
605
+ : isPreflight
606
+ ? `Pre-flight Statement Repair Invariant failed: ${identityCheck.reason ?? 'Semantic invariant failed'}`
607
+ : 'Statement Repair Intent Invariant v2 failed: Missing or failing execution proof',
608
+ };
609
+ }
610
+
611
+ const preflight = IntentValidator.validateProposal({
612
+ testFilePath: target.testFilePath,
613
+ originalCompositeFingerprint: target.originalCompositeFingerprint,
614
+ candidateElement: target.candidateElement,
615
+ intendedAction: target.intendedAction,
616
+ originalSelector: target.originalSelector,
617
+ businessOracleStatus: target.businessOracleStatus,
618
+ });
619
+
620
+ if (!preflight.isValid) {
621
+ return {
622
+ isValid: false,
623
+ assertionsPreserved: preflight.assertionsPreserved,
624
+ testBodyPreserved: preflight.testBodyPreserved,
625
+ fixturesPreserved: preflight.fixturesPreserved,
626
+ identityAndActionPreserved: preflight.identityAndActionPreserved,
627
+ diffAllowlistPassed: false,
628
+ executionVerified: false,
629
+ reason: preflight.reason,
630
+ summary: preflight.summary,
631
+ };
632
+ }
633
+
634
+ // Input data and workflow sequence checks
635
+ if (target.pageObjectOriginalSource && target.pageObjectPatchedSource) {
636
+ const inputCheck = IntentValidator.validateInputDataIntegrity(
637
+ target.pageObjectOriginalSource,
638
+ target.pageObjectPatchedSource
639
+ );
640
+ if (!inputCheck.isValid) {
641
+ return {
642
+ isValid: false,
643
+ assertionsPreserved: preflight.assertionsPreserved,
644
+ testBodyPreserved: false,
645
+ fixturesPreserved: false,
646
+ identityAndActionPreserved: preflight.identityAndActionPreserved,
647
+ diffAllowlistPassed: false,
648
+ executionVerified: false,
649
+ reason: inputCheck.reason,
650
+ summary: `Rejected: ${inputCheck.reason}`,
651
+ };
652
+ }
653
+
654
+ const workflowCheck = IntentValidator.validateWorkflowStepIntegrity(
655
+ target.pageObjectOriginalSource,
656
+ target.pageObjectPatchedSource
657
+ );
658
+ if (!workflowCheck.isValid) {
659
+ return {
660
+ isValid: false,
661
+ assertionsPreserved: preflight.assertionsPreserved,
662
+ testBodyPreserved: false,
663
+ fixturesPreserved: false,
664
+ identityAndActionPreserved: preflight.identityAndActionPreserved,
665
+ diffAllowlistPassed: false,
666
+ executionVerified: false,
667
+ reason: workflowCheck.reason,
668
+ summary: `Rejected: ${workflowCheck.reason}`,
669
+ };
670
+ }
671
+ }
672
+
673
+ // 5. D: Diff Allowlist
674
+ let diffAllowlistPassed = false;
675
+ if (
676
+ target.pageObjectOriginalSource &&
677
+ target.pageObjectPatchedSource &&
678
+ target.pageObjectClassName &&
679
+ target.targetMemberName
680
+ ) {
681
+ const diffResult = DiffAllowlistValidator.validate({
682
+ originalSource: target.pageObjectOriginalSource,
683
+ patchedSource: target.pageObjectPatchedSource,
684
+ targetClassName: target.pageObjectClassName,
685
+ targetMemberName: target.targetMemberName,
686
+ });
687
+
688
+ if (!diffResult.isAllowed) {
689
+ throw new UnauthorizedAstModificationError(diffResult.reason ?? 'Unknown violation');
690
+ }
691
+ diffAllowlistPassed = true;
692
+ } else if (isPreflight) {
693
+ diffAllowlistPassed = true;
694
+ } else {
695
+ diffAllowlistPassed = false;
696
+ }
697
+
698
+ // 6. E: Execution Verification (P0: Requires genuine, validated execution proof - no boolean shortcuts)
699
+ let executionVerified = false;
700
+ if (
701
+ target.executionProof &&
702
+ target.executionProof.passed === true &&
703
+ target.executionProof.exitCode === 0 &&
704
+ (target.executionProof.executionOutcome === 'PASS' || target.executionProof.executionOutcome === undefined) &&
705
+ target.executionProof.assertionIntegrityValid !== false
706
+ ) {
707
+ executionVerified = true;
708
+ } else {
709
+ executionVerified = false;
710
+ }
711
+
712
+ const isValid = isPreflight
713
+ ? preflight.isValid && diffAllowlistPassed
714
+ : preflight.isValid && diffAllowlistPassed && executionVerified;
715
+
716
+ return {
717
+ isValid,
718
+ assertionsPreserved: preflight.assertionsPreserved,
719
+ testBodyPreserved: preflight.testBodyPreserved,
720
+ fixturesPreserved: preflight.fixturesPreserved,
721
+ identityAndActionPreserved: preflight.identityAndActionPreserved,
722
+ diffAllowlistPassed,
723
+ executionVerified,
724
+ summary: isValid
725
+ ? isPreflight
726
+ ? 'Pre-flight Intent Invariant passed: V_pre = A ∧ T ∧ F ∧ I'
727
+ : 'Intent Invariant v2 satisfied: V = A ∧ T ∧ F ∧ I ∧ D ∧ E (Strict intent preservation proved)'
728
+ : isPreflight
729
+ ? 'Pre-flight Intent Invariant failed one or more semantic clauses'
730
+ : 'Intent Invariant v2 failed one or more clauses (Missing execution proof or diff allowlist rejection)',
731
+ };
732
+ }
733
+
734
+ private static checkActionSemantics(intendedAction: string, el: ResolvedElement): boolean {
735
+ const action = intendedAction.toLowerCase();
736
+ if (action.includes('click')) {
737
+ return (
738
+ el.tag === 'button' ||
739
+ el.tag === 'a' ||
740
+ el.role === 'button' ||
741
+ el.role === 'link' ||
742
+ el.role === 'menuitem' ||
743
+ el.role === 'tab' ||
744
+ Boolean(el.attributes?.['onclick']) ||
745
+ Boolean(el.attributes?.['href']) ||
746
+ el.tag === 'div' ||
747
+ el.tag === 'span' ||
748
+ el.tag === 'td'
749
+ );
750
+ }
751
+ if (action.includes('fill') || action.includes('type')) {
752
+ return (
753
+ el.tag === 'input' ||
754
+ el.tag === 'textarea' ||
755
+ el.role === 'textbox' ||
756
+ el.attributes['contenteditable'] === 'true'
757
+ );
758
+ }
759
+ return true;
760
+ }
761
+ }