playwright-intelligence-engine 0.0.0-stage → 2.0.1

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,226 @@
1
+ import { Project, SyntaxKind } from 'ts-morph';
2
+ import * as fs from 'fs';
3
+ import { EvidenceCollector } from './collector-interface.js';
4
+ import { UnifiedEvidenceRecord } from '../evidence/evidence-model.js';
5
+
6
+ export interface StaticAstInput {
7
+ targetFilePath: string;
8
+ sourceContent?: string;
9
+ executionId?: string;
10
+ }
11
+
12
+ export interface ExtractedLocatorAst {
13
+ className: string | undefined;
14
+ propertyName: string;
15
+ method: string;
16
+ selectorText: string;
17
+ line: number;
18
+ pattern: 'property-initializer' | 'getter' | 'constructor-assignment' | 'inline';
19
+ }
20
+
21
+ export interface ExtractedActionAst {
22
+ action: string;
23
+ line: number;
24
+ text: string;
25
+ }
26
+
27
+ export interface ExtractedAssertionAst {
28
+ assertion: string;
29
+ line: number;
30
+ text: string;
31
+ }
32
+
33
+ export class StaticAstCollector implements EvidenceCollector<StaticAstInput> {
34
+ public readonly name = 'StaticAstCollector';
35
+ public readonly source = 'static-ast' as const;
36
+
37
+ public async collect(input: StaticAstInput): Promise<UnifiedEvidenceRecord[]> {
38
+ const executionId = input.executionId ?? `exec-${Date.now()}`;
39
+ const timestamp = Date.now();
40
+
41
+ let content = input.sourceContent;
42
+ if (!content && fs.existsSync(input.targetFilePath)) {
43
+ content = fs.readFileSync(input.targetFilePath, 'utf-8');
44
+ }
45
+
46
+ if (!content) {
47
+ return [
48
+ {
49
+ evidenceId: `ast-${timestamp}-${Math.random().toString(36).slice(2, 8)}`,
50
+ executionId,
51
+ source: 'static-ast',
52
+ timestamp,
53
+ evidenceType: 'ast-analysis',
54
+ payload: {
55
+ filePath: input.targetFilePath,
56
+ error: 'File does not exist or empty content',
57
+ locators: [],
58
+ actions: [],
59
+ assertions: [],
60
+ imports: [],
61
+ isPageObject: false,
62
+ isSpec: false,
63
+ },
64
+ reliability: 'LOW',
65
+ provenance: {
66
+ collector: this.name,
67
+ collectedAt: timestamp,
68
+ captureMethod: 'ts-morph-ast-inspection',
69
+ sourceUri: input.targetFilePath,
70
+ },
71
+ redactionStatus: { isRedacted: false },
72
+ },
73
+ ];
74
+ }
75
+
76
+ const project = new Project({ useInMemoryFileSystem: true });
77
+ const sourceFile = project.createSourceFile(input.targetFilePath, content);
78
+
79
+ const locators: ExtractedLocatorAst[] = [];
80
+ const actions: ExtractedActionAst[] = [];
81
+ const assertions: ExtractedAssertionAst[] = [];
82
+ const imports: string[] = [];
83
+
84
+ // Check imports
85
+ for (const imp of sourceFile.getImportDeclarations()) {
86
+ imports.push(imp.getModuleSpecifierValue());
87
+ }
88
+
89
+ const classes = sourceFile.getClasses();
90
+ const isPageObject = classes.length > 0;
91
+ const isSpec = input.targetFilePath.includes('.spec.') || input.targetFilePath.includes('.test.');
92
+
93
+ // 1. Inspect Classes for Page Object locators
94
+ for (const cls of classes) {
95
+ // Property initializers
96
+ for (const prop of cls.getProperties()) {
97
+ const init = prop.getInitializer();
98
+ if (init && (init.getText().includes('.locator(') || init.getText().includes('.getBy'))) {
99
+ locators.push({
100
+ className: cls.getName(),
101
+ propertyName: prop.getName(),
102
+ method: this.extractLocatorMethod(init.getText()),
103
+ selectorText: init.getText(),
104
+ line: prop.getStartLineNumber(),
105
+ pattern: 'property-initializer',
106
+ });
107
+ }
108
+ }
109
+
110
+ // Getters
111
+ for (const getProp of cls.getGetAccessors()) {
112
+ const returnStmt = getProp.getFirstDescendantByKind(SyntaxKind.ReturnStatement);
113
+ if (returnStmt) {
114
+ const expr = returnStmt.getExpression();
115
+ if (expr && (expr.getText().includes('.locator(') || expr.getText().includes('.getBy'))) {
116
+ locators.push({
117
+ className: cls.getName(),
118
+ propertyName: getProp.getName(),
119
+ method: this.extractLocatorMethod(expr.getText()),
120
+ selectorText: expr.getText(),
121
+ line: getProp.getStartLineNumber(),
122
+ pattern: 'getter',
123
+ });
124
+ }
125
+ }
126
+ }
127
+
128
+ // Constructor assignments
129
+ for (const ctor of cls.getConstructors()) {
130
+ for (const stmt of ctor.getStatements()) {
131
+ const text = stmt.getText();
132
+ if (text.startsWith('this.') && (text.includes('.locator(') || text.includes('.getBy'))) {
133
+ const parts = text.split('=');
134
+ const propName = (parts[0] ?? '').replace('this.', '').trim();
135
+ locators.push({
136
+ className: cls.getName(),
137
+ propertyName: propName,
138
+ method: this.extractLocatorMethod(text),
139
+ selectorText: text,
140
+ line: stmt.getStartLineNumber(),
141
+ pattern: 'constructor-assignment',
142
+ });
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ // 2. Inspect CallExpressions for test actions and assertions (only inline calls outside class members)
149
+ for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
150
+ const expr = call.getExpression();
151
+ const exprText = expr.getText();
152
+
153
+ // Inline locators (page.locator(...)) - only record if not already part of a class member
154
+ const isInsideClass = call.getFirstAncestorByKind(SyntaxKind.ClassDeclaration);
155
+ if (!isInsideClass && (exprText.endsWith('.locator') || exprText.includes('.getBy'))) {
156
+ locators.push({
157
+ className: undefined,
158
+ propertyName: 'inline',
159
+ method: this.extractLocatorMethod(call.getText()),
160
+ selectorText: call.getText(),
161
+ line: call.getStartLineNumber(),
162
+ pattern: 'inline',
163
+ });
164
+ }
165
+
166
+ // Actions
167
+ if (
168
+ exprText.endsWith('.click') ||
169
+ exprText.endsWith('.fill') ||
170
+ exprText.endsWith('.press') ||
171
+ exprText.endsWith('.type') ||
172
+ exprText.endsWith('.check') ||
173
+ exprText.endsWith('.selectOption') ||
174
+ exprText.endsWith('.goto')
175
+ ) {
176
+ actions.push({
177
+ action: exprText.split('.').pop() ?? 'action',
178
+ line: call.getStartLineNumber(),
179
+ text: call.getText(),
180
+ });
181
+ }
182
+
183
+ // Assertions
184
+ if (exprText.startsWith('expect(')) {
185
+ assertions.push({
186
+ assertion: call.getText(),
187
+ line: call.getStartLineNumber(),
188
+ text: call.getText(),
189
+ });
190
+ }
191
+ }
192
+
193
+ return [
194
+ {
195
+ evidenceId: `ast-${timestamp}-${Math.random().toString(36).slice(2, 8)}`,
196
+ executionId,
197
+ source: 'static-ast',
198
+ timestamp,
199
+ evidenceType: 'ast-analysis',
200
+ payload: {
201
+ filePath: input.targetFilePath,
202
+ isPageObject,
203
+ isSpec,
204
+ classesCount: classes.length,
205
+ locators,
206
+ actions,
207
+ assertions,
208
+ imports,
209
+ },
210
+ reliability: 'HIGH',
211
+ provenance: {
212
+ collector: this.name,
213
+ collectedAt: timestamp,
214
+ captureMethod: 'ts-morph-ast-inspection',
215
+ sourceUri: input.targetFilePath,
216
+ },
217
+ redactionStatus: { isRedacted: false },
218
+ },
219
+ ];
220
+ }
221
+
222
+ private extractLocatorMethod(text: string): string {
223
+ const match = text.match(/(locator|getByRole|getByText|getByTestId|getByLabel|getByPlaceholder|getByAltText|getByTitle)/);
224
+ return match && match[1] ? match[1] : 'locator';
225
+ }
226
+ }
@@ -0,0 +1,66 @@
1
+ import { EvidenceCollector } from './collector-interface.js';
2
+ import { UnifiedEvidenceRecord } from '../evidence/evidence-model.js';
3
+ import { ArchiveReader } from '../trace/archive-reader.js';
4
+ import { TraceParser } from '../trace/trace-parser.js';
5
+ import { EvidenceNormalizer } from '../evidence/evidence-normalizer.js';
6
+
7
+ export interface TraceCollectorInput {
8
+ archivePath: string;
9
+ executionId?: string;
10
+ }
11
+
12
+ export class TraceCollector implements EvidenceCollector<TraceCollectorInput> {
13
+ public readonly name = 'TraceCollector';
14
+ public readonly source = 'trace' as const;
15
+
16
+ public async collect(input: TraceCollectorInput): Promise<UnifiedEvidenceRecord[]> {
17
+ const executionId = input.executionId ?? `exec-${Date.now()}`;
18
+ const timestamp = Date.now();
19
+
20
+ try {
21
+ const { traceEntryName, networkEntryName, traceEntryNames, networkEntryNames } = ArchiveReader.findTraceFileEntries(input.archivePath);
22
+ if (!traceEntryName) {
23
+ throw new Error(`No .trace entry found inside archive: ${input.archivePath}`);
24
+ }
25
+ const traceText = await ArchiveReader.readEntriesAsText(input.archivePath, traceEntryNames ?? [traceEntryName]);
26
+ const networkText = (networkEntryNames ?? (networkEntryName ? [networkEntryName] : [])).length > 0
27
+ ? await ArchiveReader.readEntriesAsText(input.archivePath, networkEntryNames ?? [networkEntryName!])
28
+ : '';
29
+ const traceLines = traceText.split('\n');
30
+ const networkLines = networkText ? networkText.split('\n') : [];
31
+ const context = TraceParser.assembleDiagnosticContext(traceLines, networkLines);
32
+
33
+ const records = EvidenceNormalizer.fromDiagnosticContext(context, executionId);
34
+
35
+ // Enhance provenance with archive file path
36
+ for (const rec of records) {
37
+ rec.provenance.sourceUri = input.archivePath;
38
+ }
39
+
40
+ return records;
41
+ } catch (err: any) {
42
+ return [
43
+ {
44
+ evidenceId: `trace-err-${timestamp}`,
45
+ executionId,
46
+ source: 'trace',
47
+ timestamp,
48
+ evidenceType: 'trace-ingestion-failure',
49
+ payload: {
50
+ archivePath: input.archivePath,
51
+ error: err?.message || 'Failed to parse trace archive',
52
+ },
53
+ reliability: 'LOW',
54
+ provenance: {
55
+ collector: this.name,
56
+ collectedAt: timestamp,
57
+ captureMethod: 'archive-reader',
58
+ sourceUri: input.archivePath,
59
+ },
60
+ redactionStatus: { isRedacted: false },
61
+ limitations: [err?.message || 'Trace parse failure'],
62
+ },
63
+ ];
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,114 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+
4
+ export const PROJECT_CONFIG_VERSION = 1;
5
+
6
+ export interface PieProjectConfig {
7
+ version: typeof PROJECT_CONFIG_VERSION;
8
+ projectRoot: string;
9
+ createdAt: string;
10
+ updatedAt: string;
11
+ test: {
12
+ packageManager: 'npm' | 'pnpm' | 'yarn' | 'unknown';
13
+ command?: string | undefined;
14
+ traceDirectories: string[];
15
+ };
16
+ diagnostics: {
17
+ failClosed: true;
18
+ requireDomEvidence: boolean;
19
+ allowDirectWorkspaceMutation: false;
20
+ };
21
+ memory: {
22
+ ledgerPath: string;
23
+ repositoryProfilePath: string;
24
+ };
25
+ }
26
+
27
+ export interface InitProjectOptions {
28
+ force?: boolean | undefined;
29
+ now?: Date | undefined;
30
+ }
31
+
32
+ export interface InitProjectResult {
33
+ config: PieProjectConfig;
34
+ configPath: string;
35
+ created: boolean;
36
+ }
37
+
38
+ function packageManagerFromFiles(files: Set<string>): PieProjectConfig['test']['packageManager'] {
39
+ if (files.has('pnpm-lock.yaml')) return 'pnpm';
40
+ if (files.has('yarn.lock')) return 'yarn';
41
+ if (files.has('package-lock.json')) return 'npm';
42
+ return 'unknown';
43
+ }
44
+
45
+ async function readPackageScripts(projectRoot: string): Promise<Record<string, string>> {
46
+ try {
47
+ const raw = await fs.readFile(path.join(projectRoot, 'package.json'), 'utf8');
48
+ const parsed = JSON.parse(raw) as { scripts?: Record<string, string> };
49
+ return parsed.scripts ?? {};
50
+ } catch {
51
+ return {};
52
+ }
53
+ }
54
+
55
+ function chooseTestCommand(scripts: Record<string, string>): string | undefined {
56
+ return ['test:e2e', 'test:smoke', 'test', 'e2e'].find((name) => Boolean(scripts[name]));
57
+ }
58
+
59
+ export async function initProjectConfig(
60
+ workspaceRoot = process.cwd(),
61
+ options: InitProjectOptions = {},
62
+ ): Promise<InitProjectResult> {
63
+ const projectRoot = path.resolve(workspaceRoot);
64
+ const pieDirectory = path.join(projectRoot, '.pie');
65
+ const configPath = path.join(pieDirectory, 'config.json');
66
+ const exists = await fs.access(configPath).then(() => true).catch(() => false);
67
+
68
+ if (exists && !options.force) {
69
+ const existing = await loadProjectConfig(projectRoot);
70
+ return { config: existing, configPath, created: false };
71
+ }
72
+
73
+ const entries = await fs.readdir(projectRoot, { withFileTypes: true });
74
+ const fileNames = new Set(entries.filter((entry) => entry.isFile()).map((entry) => entry.name));
75
+ const scripts = await readPackageScripts(projectRoot);
76
+ const timestamp = (options.now ?? new Date()).toISOString();
77
+ const config: PieProjectConfig = {
78
+ version: PROJECT_CONFIG_VERSION,
79
+ projectRoot,
80
+ createdAt: timestamp,
81
+ updatedAt: timestamp,
82
+ test: {
83
+ packageManager: packageManagerFromFiles(fileNames),
84
+ command: chooseTestCommand(scripts),
85
+ traceDirectories: ['test-results'],
86
+ },
87
+ diagnostics: {
88
+ failClosed: true,
89
+ requireDomEvidence: true,
90
+ allowDirectWorkspaceMutation: false,
91
+ },
92
+ memory: {
93
+ ledgerPath: '.pw-intelligence/stability-ledger.json',
94
+ repositoryProfilePath: '.pie/repository-profile.json',
95
+ },
96
+ };
97
+
98
+ await fs.mkdir(pieDirectory, { recursive: true });
99
+ await fs.writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
100
+ return { config, configPath, created: true };
101
+ }
102
+
103
+ export async function loadProjectConfig(workspaceRoot = process.cwd()): Promise<PieProjectConfig> {
104
+ const configPath = path.join(path.resolve(workspaceRoot), '.pie', 'config.json');
105
+ const raw = await fs.readFile(configPath, 'utf8');
106
+ const parsed = JSON.parse(raw) as Partial<PieProjectConfig>;
107
+ if (parsed.version !== PROJECT_CONFIG_VERSION) {
108
+ throw new Error(`Unsupported PIE project config version '${String(parsed.version)}'`);
109
+ }
110
+ if (!parsed.projectRoot || !parsed.test || !parsed.diagnostics || !parsed.memory) {
111
+ throw new Error(`Invalid PIE project config at '${configPath}'`);
112
+ }
113
+ return parsed as PieProjectConfig;
114
+ }
@@ -0,0 +1,90 @@
1
+ export class PlaywrightIntelligenceError extends Error {
2
+ constructor(message: string, public readonly code: string) {
3
+ super(message);
4
+ this.name = 'PlaywrightIntelligenceError';
5
+ Object.setPrototypeOf(this, new.target.prototype);
6
+ }
7
+ }
8
+
9
+ export class UnsupportedTraceVersionError extends PlaywrightIntelligenceError {
10
+ constructor(version: number | string, message?: string) {
11
+ super(
12
+ message ?? `Unsupported Playwright trace version: ${version}`,
13
+ 'UNSUPPORTED_TRACE_VERSION'
14
+ );
15
+ this.name = 'UnsupportedTraceVersionError';
16
+ }
17
+ }
18
+
19
+ export class TraceCorruptedError extends PlaywrightIntelligenceError {
20
+ constructor(path: string, reason: string) {
21
+ super(`Trace archive at ${path} is corrupted: ${reason}`, 'TRACE_CORRUPTED');
22
+ this.name = 'TraceCorruptedError';
23
+ }
24
+ }
25
+
26
+ export class ZipSlipSecurityError extends PlaywrightIntelligenceError {
27
+ constructor(entryPath: string) {
28
+ super(
29
+ `Security violation: Zip entry ${entryPath} attempts path traversal outside target directory`,
30
+ 'ZIP_SLIP_ATTACK_DETECTED'
31
+ );
32
+ this.name = 'ZipSlipSecurityError';
33
+ }
34
+ }
35
+
36
+ export class AbstentionError extends PlaywrightIntelligenceError {
37
+ constructor(public readonly reason: string, public readonly failureCategory: string) {
38
+ super(`Engine abstains from repair: ${reason} (Category: ${failureCategory})`, 'REPAIR_ABSTAINED');
39
+ this.name = 'AbstentionError';
40
+ }
41
+ }
42
+
43
+ export class AssertionTamperedError extends PlaywrightIntelligenceError {
44
+ constructor(expectedFingerprint: string, actualFingerprint: string) {
45
+ super(
46
+ `Intent violation: Assertion SHA-256 fingerprint changed after patch (expected ${expectedFingerprint}, got ${actualFingerprint})`,
47
+ 'ASSERTION_TAMPERED'
48
+ );
49
+ this.name = 'AssertionTamperedError';
50
+ }
51
+ }
52
+
53
+ export class WorktreeOperationError extends PlaywrightIntelligenceError {
54
+ constructor(operation: string, details: string) {
55
+ super(`Worktree operation '${operation}' failed: ${details}`, 'WORKTREE_ERROR');
56
+ this.name = 'WorktreeOperationError';
57
+ }
58
+ }
59
+
60
+ export class UnauthorizedAstModificationError extends PlaywrightIntelligenceError {
61
+ constructor(details: string) {
62
+ super(
63
+ `Diff allowlist violation: Unauthorized AST modification detected (${details}). Only targeted locator declarations may be altered.`,
64
+ 'UNAUTHORIZED_AST_MODIFICATION'
65
+ );
66
+ this.name = 'UnauthorizedAstModificationError';
67
+ }
68
+ }
69
+
70
+ export class IntentInvariantViolationError extends PlaywrightIntelligenceError {
71
+ constructor(invariantName: string, details: string) {
72
+ super(
73
+ `Intent Invariant v2 violation [${invariantName}]: ${details}`,
74
+ 'INTENT_INVARIANT_VIOLATION'
75
+ );
76
+ this.name = 'IntentInvariantViolationError';
77
+ }
78
+ }
79
+
80
+ export class InsufficientIdentifiersError extends PlaywrightIntelligenceError {
81
+ constructor(tag: string, details?: string) {
82
+ super(
83
+ `Element <${tag}> lacks distinctive identifying attributes: ${details ?? 'Bare tag fallbacks are strictly prohibited.'}`,
84
+ 'INSUFFICIENT_IDENTIFIERS'
85
+ );
86
+ this.name = 'InsufficientIdentifiersError';
87
+ }
88
+ }
89
+
90
+
@@ -0,0 +1,94 @@
1
+ import { z } from 'zod';
2
+
3
+ export const NetworkEventSchema = z.object({
4
+ url: z.string(),
5
+ method: z.string(),
6
+ status: z.number(),
7
+ statusText: z.string().optional(),
8
+ headers: z.record(z.string(), z.string()).optional(),
9
+ timestamp: z.number(),
10
+ durationMs: z.number().optional(),
11
+ errorText: z.string().optional(),
12
+ requestId: z.string().optional(),
13
+ frameId: z.string().optional(),
14
+ resourceType: z.string().optional(),
15
+ initiator: z.string().optional(),
16
+ });
17
+
18
+ export type NetworkEvent = z.infer<typeof NetworkEventSchema>;
19
+
20
+ export const ConsoleEventSchema = z.object({
21
+ type: z.enum(['log', 'info', 'warn', 'error', 'debug']),
22
+ text: z.string(),
23
+ timestamp: z.number(),
24
+ location: z.object({
25
+ url: z.string().optional(),
26
+ lineNumber: z.number().optional(),
27
+ columnNumber: z.number().optional(),
28
+ }).optional(),
29
+ });
30
+
31
+ export type ConsoleEvent = z.infer<typeof ConsoleEventSchema>;
32
+
33
+ export const FailureCategorySchema = z.enum([
34
+ 'LOCATOR_DRIFT',
35
+ 'AUTH_EXPIRED',
36
+ 'AUTH_SESSION_EXPIRED',
37
+ 'TIMING_RACE',
38
+ 'DYNAMIC_CONTENT_SLOW',
39
+ 'BACKEND_500',
40
+ 'ENVIRONMENT_FAILURE',
41
+ 'ASSERTION_FAILURE',
42
+ 'ASSERTION_FAILED',
43
+ 'NETWORK_OFFLINE',
44
+ 'AMBIGUOUS_MATCH',
45
+ 'OBSTRUCTED_ELEMENT',
46
+ 'DISABLED_ELEMENT',
47
+ 'FRAME_OR_IFRAME',
48
+ 'HYDRATION_OR_TIMING',
49
+ 'MIXED_FAILURE',
50
+ 'INCOMPLETE_EVIDENCE',
51
+ 'UNSUPPORTED_TRACE_FORMAT',
52
+ 'UNKNOWN_ERROR',
53
+ ]);
54
+
55
+ export type FailureCategory = z.infer<typeof FailureCategorySchema>;
56
+
57
+ export const FailedActionSchema = z.object({
58
+ callId: z.string(),
59
+ action: z.string(), // e.g. "click", "fill", "waitFor"
60
+ selector: z.string().optional(), // original failed locator
61
+ sourceFile: z.string().optional(),
62
+ line: z.number().optional(),
63
+ column: z.number().optional(),
64
+ errorStack: z.string().optional(),
65
+ errorMessage: z.string().optional(),
66
+ durationMs: z.number().optional(),
67
+ timestamp: z.number().optional(),
68
+ frameId: z.string().optional(),
69
+ logs: z.array(z.string()).optional(),
70
+ });
71
+
72
+ export type FailedAction = z.infer<typeof FailedActionSchema>;
73
+
74
+ export const DiagnosticContextSchema = z.object({
75
+ playwrightVersion: z.string(),
76
+ traceFormatVersion: z.number(),
77
+ failedAction: FailedActionSchema,
78
+ snapshots: z.object({
79
+ before: z.string().optional(),
80
+ action: z.string().optional(),
81
+ after: z.string().optional(),
82
+ }),
83
+ networkEvents: z.array(NetworkEventSchema),
84
+ consoleEvents: z.array(ConsoleEventSchema),
85
+ failureCategory: FailureCategorySchema.optional(),
86
+ evidenceCompleteness: z.object({
87
+ domAvailable: z.boolean(),
88
+ networkAvailable: z.boolean(),
89
+ sourceAvailable: z.boolean(),
90
+ }),
91
+ });
92
+
93
+ export type DiagnosticContext = z.infer<typeof DiagnosticContextSchema>;
94
+
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+
3
+ export const SourceLocationSchema = z.object({
4
+ filePath: z.string(),
5
+ className: z.string(),
6
+ memberName: z.string(),
7
+ nodeKind: z.enum([
8
+ 'property',
9
+ 'constructor-assignment',
10
+ 'getter-return',
11
+ 'parameterless-factory',
12
+ 'locator-constant',
13
+ ]),
14
+ line: z.number(),
15
+ column: z.number().optional(),
16
+ });
17
+
18
+ export type SourceLocation = z.infer<typeof SourceLocationSchema>;
19
+
20
+ export const BusinessOracleStatusSchema = z.enum([
21
+ 'verified',
22
+ 'contradicted',
23
+ 'unavailable',
24
+ ]);
25
+
26
+ export type BusinessOracleStatus = z.infer<typeof BusinessOracleStatusSchema>;
27
+
28
+ export const RepairEvidenceSchema = z.object({
29
+ originalActionId: z.string(),
30
+ originalSelector: z.string(),
31
+ candidateSelector: z.string(),
32
+ candidateScore: z.number(),
33
+ sourceLocation: SourceLocationSchema,
34
+ targetIdentityEvidence: z.array(z.string()),
35
+ assertionFingerprint: z.string(), // SHA-256 of AST expect() blocks (must remain identical)
36
+ businessOracleStatus: BusinessOracleStatusSchema,
37
+ verificationWorktreeId: z.string(),
38
+ repairedTestDurationMs: z.number(),
39
+ timestamp: z.number(),
40
+ repairedSuccessfully: z.boolean(),
41
+ notes: z.string().optional(),
42
+ });
43
+
44
+ export type RepairEvidence = z.infer<typeof RepairEvidenceSchema>;
45
+
@@ -0,0 +1,25 @@
1
+ import { execFileSync } from 'node:child_process';
2
+
3
+ /**
4
+ * Product identity is kept in one place so the CLI, MCP server, and execution
5
+ * proofs cannot silently advertise different versions.
6
+ */
7
+ export const PACKAGE_VERSION = '2.0.1';
8
+ export const ENGINE_MILESTONE = '2.0.1';
9
+ export const PROOF_VERSION = ENGINE_MILESTONE;
10
+
11
+ export interface RuntimeProvenance {
12
+ sourceRevision: string;
13
+ workspaceDirty: boolean;
14
+ }
15
+
16
+ export function getRuntimeProvenance(root = process.cwd()): RuntimeProvenance {
17
+ try {
18
+ const sourceRevision = execFileSync('git', ['rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim() || 'unknown';
19
+ const status = execFileSync('git', ['status', '--porcelain'], { cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
20
+ return { sourceRevision, workspaceDirty: status.trim().length > 0 };
21
+ } catch {
22
+ return { sourceRevision: 'unknown', workspaceDirty: false };
23
+ }
24
+ }
25
+