sela-core 0.1.0-alpha.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 (267) hide show
  1. package/README.md +103 -0
  2. package/bin/sela.js +3 -0
  3. package/dist/cli/ErrorHandler.d.ts +10 -0
  4. package/dist/cli/ErrorHandler.d.ts.map +1 -0
  5. package/dist/cli/ErrorHandler.js +70 -0
  6. package/dist/cli/commands/bulk.d.ts +3 -0
  7. package/dist/cli/commands/bulk.d.ts.map +1 -0
  8. package/dist/cli/commands/bulk.js +158 -0
  9. package/dist/cli/commands/find.d.ts +3 -0
  10. package/dist/cli/commands/find.d.ts.map +1 -0
  11. package/dist/cli/commands/find.js +51 -0
  12. package/dist/cli/commands/init.d.ts +3 -0
  13. package/dist/cli/commands/init.d.ts.map +1 -0
  14. package/dist/cli/commands/init.js +166 -0
  15. package/dist/cli/commands/list.d.ts +3 -0
  16. package/dist/cli/commands/list.d.ts.map +1 -0
  17. package/dist/cli/commands/list.js +56 -0
  18. package/dist/cli/commands/merge.d.ts +13 -0
  19. package/dist/cli/commands/merge.d.ts.map +1 -0
  20. package/dist/cli/commands/merge.js +119 -0
  21. package/dist/cli/commands/refactor.d.ts +3 -0
  22. package/dist/cli/commands/refactor.d.ts.map +1 -0
  23. package/dist/cli/commands/refactor.js +30 -0
  24. package/dist/cli/commands/showReport.d.ts +3 -0
  25. package/dist/cli/commands/showReport.d.ts.map +1 -0
  26. package/dist/cli/commands/showReport.js +82 -0
  27. package/dist/cli/commands/status.d.ts +3 -0
  28. package/dist/cli/commands/status.d.ts.map +1 -0
  29. package/dist/cli/commands/status.js +51 -0
  30. package/dist/cli/commands/sync.d.ts +3 -0
  31. package/dist/cli/commands/sync.d.ts.map +1 -0
  32. package/dist/cli/commands/sync.js +131 -0
  33. package/dist/cli/index.d.ts +2 -0
  34. package/dist/cli/index.d.ts.map +1 -0
  35. package/dist/cli/index.js +94 -0
  36. package/dist/cli/ui/DnaTable.d.ts +3 -0
  37. package/dist/cli/ui/DnaTable.d.ts.map +1 -0
  38. package/dist/cli/ui/DnaTable.js +77 -0
  39. package/dist/cli/ui/LocatorPicker.d.ts +8 -0
  40. package/dist/cli/ui/LocatorPicker.d.ts.map +1 -0
  41. package/dist/cli/ui/LocatorPicker.js +33 -0
  42. package/dist/cli/ui/ProgressReporter.d.ts +11 -0
  43. package/dist/cli/ui/ProgressReporter.d.ts.map +1 -0
  44. package/dist/cli/ui/ProgressReporter.js +33 -0
  45. package/dist/cli/ui/RefactorWizard.d.ts +26 -0
  46. package/dist/cli/ui/RefactorWizard.d.ts.map +1 -0
  47. package/dist/cli/ui/RefactorWizard.js +295 -0
  48. package/dist/config/ConfigLoader.d.ts +16 -0
  49. package/dist/config/ConfigLoader.d.ts.map +1 -0
  50. package/dist/config/ConfigLoader.js +185 -0
  51. package/dist/config/DryRunGuard.d.ts +14 -0
  52. package/dist/config/DryRunGuard.d.ts.map +1 -0
  53. package/dist/config/DryRunGuard.js +80 -0
  54. package/dist/config/PathScopeGuard.d.ts +42 -0
  55. package/dist/config/PathScopeGuard.d.ts.map +1 -0
  56. package/dist/config/PathScopeGuard.js +192 -0
  57. package/dist/config/SelaConfig.d.ts +178 -0
  58. package/dist/config/SelaConfig.d.ts.map +1 -0
  59. package/dist/config/SelaConfig.js +141 -0
  60. package/dist/config/defineConfig.d.ts +3 -0
  61. package/dist/config/defineConfig.d.ts.map +1 -0
  62. package/dist/config/defineConfig.js +9 -0
  63. package/dist/engine/FixwrightEngine.d.ts +24 -0
  64. package/dist/engine/FixwrightEngine.d.ts.map +1 -0
  65. package/dist/engine/FixwrightEngine.js +403 -0
  66. package/dist/engine/HealingRegistry.d.ts +40 -0
  67. package/dist/engine/HealingRegistry.d.ts.map +1 -0
  68. package/dist/engine/HealingRegistry.js +99 -0
  69. package/dist/engine/SelaEngine.d.ts +57 -0
  70. package/dist/engine/SelaEngine.d.ts.map +1 -0
  71. package/dist/engine/SelaEngine.js +1146 -0
  72. package/dist/engine/singleton.d.ts +3 -0
  73. package/dist/engine/singleton.d.ts.map +1 -0
  74. package/dist/engine/singleton.js +5 -0
  75. package/dist/errors/SelaError.d.ts +146 -0
  76. package/dist/errors/SelaError.d.ts.map +1 -0
  77. package/dist/errors/SelaError.js +168 -0
  78. package/dist/fixtures/expectProxy.d.ts +12 -0
  79. package/dist/fixtures/expectProxy.d.ts.map +1 -0
  80. package/dist/fixtures/expectProxy.js +246 -0
  81. package/dist/fixtures/index.d.ts +30 -0
  82. package/dist/fixtures/index.d.ts.map +1 -0
  83. package/dist/fixtures/index.js +765 -0
  84. package/dist/fixtures/moduleExpect.d.ts +2 -0
  85. package/dist/fixtures/moduleExpect.d.ts.map +1 -0
  86. package/dist/fixtures/moduleExpect.js +54 -0
  87. package/dist/fixtures/proxyTag.d.ts +12 -0
  88. package/dist/fixtures/proxyTag.d.ts.map +1 -0
  89. package/dist/fixtures/proxyTag.js +45 -0
  90. package/dist/index.d.ts +9 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +31 -0
  93. package/dist/reporter/SelaReporter.d.ts +165 -0
  94. package/dist/reporter/SelaReporter.d.ts.map +1 -0
  95. package/dist/reporter/SelaReporter.js +517 -0
  96. package/dist/services/ASTSourceUpdater.d.ts +143 -0
  97. package/dist/services/ASTSourceUpdater.d.ts.map +1 -0
  98. package/dist/services/ASTSourceUpdater.js +3514 -0
  99. package/dist/services/AnchorResolver.d.ts +157 -0
  100. package/dist/services/AnchorResolver.d.ts.map +1 -0
  101. package/dist/services/AnchorResolver.js +289 -0
  102. package/dist/services/ArgumentTypeAnalyzer.d.ts +26 -0
  103. package/dist/services/ArgumentTypeAnalyzer.d.ts.map +1 -0
  104. package/dist/services/ArgumentTypeAnalyzer.js +92 -0
  105. package/dist/services/BlastRadiusAnalyzer.d.ts +15 -0
  106. package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -0
  107. package/dist/services/BlastRadiusAnalyzer.js +107 -0
  108. package/dist/services/ChainValidator.d.ts +76 -0
  109. package/dist/services/ChainValidator.d.ts.map +1 -0
  110. package/dist/services/ChainValidator.js +570 -0
  111. package/dist/services/CrossFileHealer.d.ts +6 -0
  112. package/dist/services/CrossFileHealer.d.ts.map +1 -0
  113. package/dist/services/CrossFileHealer.js +135 -0
  114. package/dist/services/DecisionEngine.d.ts +51 -0
  115. package/dist/services/DecisionEngine.d.ts.map +1 -0
  116. package/dist/services/DecisionEngine.js +260 -0
  117. package/dist/services/DefinitionTracer.d.ts +41 -0
  118. package/dist/services/DefinitionTracer.d.ts.map +1 -0
  119. package/dist/services/DefinitionTracer.js +366 -0
  120. package/dist/services/DnaEditorService.d.ts +31 -0
  121. package/dist/services/DnaEditorService.d.ts.map +1 -0
  122. package/dist/services/DnaEditorService.js +217 -0
  123. package/dist/services/DnaIndexService.d.ts +24 -0
  124. package/dist/services/DnaIndexService.d.ts.map +1 -0
  125. package/dist/services/DnaIndexService.js +131 -0
  126. package/dist/services/HealBudget.d.ts +32 -0
  127. package/dist/services/HealBudget.d.ts.map +1 -0
  128. package/dist/services/HealBudget.js +85 -0
  129. package/dist/services/HealReportService.d.ts +161 -0
  130. package/dist/services/HealReportService.d.ts.map +1 -0
  131. package/dist/services/HealReportService.js +1039 -0
  132. package/dist/services/HealingAdvisory.d.ts +30 -0
  133. package/dist/services/HealingAdvisory.d.ts.map +1 -0
  134. package/dist/services/HealingAdvisory.js +51 -0
  135. package/dist/services/HealingCacheService.d.ts +135 -0
  136. package/dist/services/HealingCacheService.d.ts.map +1 -0
  137. package/dist/services/HealingCacheService.js +404 -0
  138. package/dist/services/HealthReportService.d.ts +10 -0
  139. package/dist/services/HealthReportService.d.ts.map +1 -0
  140. package/dist/services/HealthReportService.js +84 -0
  141. package/dist/services/InitializerUpdater.d.ts +16 -0
  142. package/dist/services/InitializerUpdater.d.ts.map +1 -0
  143. package/dist/services/InitializerUpdater.js +73 -0
  144. package/dist/services/IntentAuditor.d.ts +56 -0
  145. package/dist/services/IntentAuditor.d.ts.map +1 -0
  146. package/dist/services/IntentAuditor.js +326 -0
  147. package/dist/services/InteractiveReview.d.ts +15 -0
  148. package/dist/services/InteractiveReview.d.ts.map +1 -0
  149. package/dist/services/InteractiveReview.js +128 -0
  150. package/dist/services/LLMService.d.ts +121 -0
  151. package/dist/services/LLMService.d.ts.map +1 -0
  152. package/dist/services/LLMService.js +475 -0
  153. package/dist/services/MutationApplier.d.ts +69 -0
  154. package/dist/services/MutationApplier.d.ts.map +1 -0
  155. package/dist/services/MutationApplier.js +360 -0
  156. package/dist/services/PRAutomationService.d.ts +50 -0
  157. package/dist/services/PRAutomationService.d.ts.map +1 -0
  158. package/dist/services/PRAutomationService.js +760 -0
  159. package/dist/services/PendingPromptLedger.d.ts +51 -0
  160. package/dist/services/PendingPromptLedger.d.ts.map +1 -0
  161. package/dist/services/PendingPromptLedger.js +205 -0
  162. package/dist/services/ReportGenerator.d.ts +156 -0
  163. package/dist/services/ReportGenerator.d.ts.map +1 -0
  164. package/dist/services/ReportGenerator.js +278 -0
  165. package/dist/services/ReportMergeService.d.ts +95 -0
  166. package/dist/services/ReportMergeService.d.ts.map +1 -0
  167. package/dist/services/ReportMergeService.js +0 -0
  168. package/dist/services/SafetyGuard.d.ts +112 -0
  169. package/dist/services/SafetyGuard.d.ts.map +1 -0
  170. package/dist/services/SafetyGuard.js +87 -0
  171. package/dist/services/Sanitizer.d.ts +28 -0
  172. package/dist/services/Sanitizer.d.ts.map +1 -0
  173. package/dist/services/Sanitizer.js +142 -0
  174. package/dist/services/SanitizingAnthropic.d.ts +19 -0
  175. package/dist/services/SanitizingAnthropic.d.ts.map +1 -0
  176. package/dist/services/SanitizingAnthropic.js +84 -0
  177. package/dist/services/SelectorSanitizer.d.ts +52 -0
  178. package/dist/services/SelectorSanitizer.d.ts.map +1 -0
  179. package/dist/services/SelectorSanitizer.js +318 -0
  180. package/dist/services/SnapshotService.d.ts +11 -0
  181. package/dist/services/SnapshotService.d.ts.map +1 -0
  182. package/dist/services/SnapshotService.js +352 -0
  183. package/dist/services/SourceLinkService.d.ts +26 -0
  184. package/dist/services/SourceLinkService.d.ts.map +1 -0
  185. package/dist/services/SourceLinkService.js +165 -0
  186. package/dist/services/SourceUpdater.d.ts +45 -0
  187. package/dist/services/SourceUpdater.d.ts.map +1 -0
  188. package/dist/services/SourceUpdater.js +1091 -0
  189. package/dist/services/TemplateDiffService.d.ts +25 -0
  190. package/dist/services/TemplateDiffService.d.ts.map +1 -0
  191. package/dist/services/TemplateDiffService.js +334 -0
  192. package/dist/services/TraceBackEngine.d.ts +67 -0
  193. package/dist/services/TraceBackEngine.d.ts.map +1 -0
  194. package/dist/services/TraceBackEngine.js +672 -0
  195. package/dist/services/WorkspaceSnapshotService.d.ts +71 -0
  196. package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -0
  197. package/dist/services/WorkspaceSnapshotService.js +200 -0
  198. package/dist/services/safety/PipelineContext.d.ts +63 -0
  199. package/dist/services/safety/PipelineContext.d.ts.map +1 -0
  200. package/dist/services/safety/PipelineContext.js +34 -0
  201. package/dist/services/safety/roleClassifier.d.ts +4 -0
  202. package/dist/services/safety/roleClassifier.d.ts.map +1 -0
  203. package/dist/services/safety/roleClassifier.js +233 -0
  204. package/dist/services/safety/rules/ConfidenceTierRule.d.ts +3 -0
  205. package/dist/services/safety/rules/ConfidenceTierRule.d.ts.map +1 -0
  206. package/dist/services/safety/rules/ConfidenceTierRule.js +32 -0
  207. package/dist/services/safety/rules/DangerousSinkRule.d.ts +10 -0
  208. package/dist/services/safety/rules/DangerousSinkRule.d.ts.map +1 -0
  209. package/dist/services/safety/rules/DangerousSinkRule.js +53 -0
  210. package/dist/services/safety/rules/FunctionalRoleRule.d.ts +3 -0
  211. package/dist/services/safety/rules/FunctionalRoleRule.d.ts.map +1 -0
  212. package/dist/services/safety/rules/FunctionalRoleRule.js +64 -0
  213. package/dist/services/safety/rules/HardConfidenceRule.d.ts +3 -0
  214. package/dist/services/safety/rules/HardConfidenceRule.d.ts.map +1 -0
  215. package/dist/services/safety/rules/HardConfidenceRule.js +22 -0
  216. package/dist/services/safety/rules/IntentAuditorRule.d.ts +3 -0
  217. package/dist/services/safety/rules/IntentAuditorRule.d.ts.map +1 -0
  218. package/dist/services/safety/rules/IntentAuditorRule.js +97 -0
  219. package/dist/services/safety/rules/SemanticOppositeRule.d.ts +3 -0
  220. package/dist/services/safety/rules/SemanticOppositeRule.d.ts.map +1 -0
  221. package/dist/services/safety/rules/SemanticOppositeRule.js +30 -0
  222. package/dist/services/safety/rules/StructuralOnlyRule.d.ts +3 -0
  223. package/dist/services/safety/rules/StructuralOnlyRule.d.ts.map +1 -0
  224. package/dist/services/safety/rules/StructuralOnlyRule.js +38 -0
  225. package/dist/services/safety/rules/VisibilityRule.d.ts +3 -0
  226. package/dist/services/safety/rules/VisibilityRule.d.ts.map +1 -0
  227. package/dist/services/safety/rules/VisibilityRule.js +53 -0
  228. package/dist/services/safety/rules/ZeroTrustRule.d.ts +3 -0
  229. package/dist/services/safety/rules/ZeroTrustRule.d.ts.map +1 -0
  230. package/dist/services/safety/rules/ZeroTrustRule.js +37 -0
  231. package/dist/services/safety/rules/index.d.ts +3 -0
  232. package/dist/services/safety/rules/index.d.ts.map +1 -0
  233. package/dist/services/safety/rules/index.js +34 -0
  234. package/dist/services/types.d.ts +59 -0
  235. package/dist/services/types.d.ts.map +1 -0
  236. package/dist/services/types.js +2 -0
  237. package/dist/storage/SnapshotManager.d.ts +5 -0
  238. package/dist/storage/SnapshotManager.d.ts.map +1 -0
  239. package/dist/storage/SnapshotManager.js +32 -0
  240. package/dist/types/index.d.ts +95 -0
  241. package/dist/types/index.d.ts.map +1 -0
  242. package/dist/types/index.js +7 -0
  243. package/dist/utils/DOMUtils.d.ts +49 -0
  244. package/dist/utils/DOMUtils.d.ts.map +1 -0
  245. package/dist/utils/DOMUtils.js +466 -0
  246. package/dist/utils/FileLock.d.ts +44 -0
  247. package/dist/utils/FileLock.d.ts.map +1 -0
  248. package/dist/utils/FileLock.js +189 -0
  249. package/dist/utils/IsolatedDiff.d.ts +45 -0
  250. package/dist/utils/IsolatedDiff.d.ts.map +1 -0
  251. package/dist/utils/IsolatedDiff.js +382 -0
  252. package/dist/utils/StackUtils.d.ts +11 -0
  253. package/dist/utils/StackUtils.d.ts.map +1 -0
  254. package/dist/utils/StackUtils.js +120 -0
  255. package/dist/utils/SummaryTable.d.ts +17 -0
  256. package/dist/utils/SummaryTable.d.ts.map +1 -0
  257. package/dist/utils/SummaryTable.js +37 -0
  258. package/dist/utils/atomicWrite.d.ts +9 -0
  259. package/dist/utils/atomicWrite.d.ts.map +1 -0
  260. package/dist/utils/atomicWrite.js +83 -0
  261. package/dist/utils/logger.d.ts +59 -0
  262. package/dist/utils/logger.d.ts.map +1 -0
  263. package/dist/utils/logger.js +123 -0
  264. package/dist/vendor/enquirer.d.ts +33 -0
  265. package/dist/vendor/enquirer.d.ts.map +1 -0
  266. package/dist/vendor/enquirer.js +11 -0
  267. package/package.json +71 -0
@@ -0,0 +1,517 @@
1
+ "use strict";
2
+ // src/reporter/SelaReporter.ts
3
+ //
4
+ // SelaReporter - Playwright Reporter implementation that drives the
5
+ // Sela heal-and-report pipeline at the reporter layer instead of the
6
+ // fixture teardown layer. The fixture path remains the primary trigger
7
+ // for in-test heals; this reporter is the SAFETY NET for worker crashes,
8
+ // timeouts, and any failure mode that skips fixture teardown.
9
+ //
10
+ // Responsibilities:
11
+ // 1. onBegin - flips SELA_REPORTER_ACTIVE, installs SIGINT/SIGTERM
12
+ // graceful-shutdown handlers.
13
+ // 2. onTestEnd - extracts the first PNG screenshot from
14
+ // TestResult.attachments and converts it to Base64 IMMEDIATELY.
15
+ // Playwright's temp folder is cleaned up between runs, so the
16
+ // bytes MUST be captured into memory before the reporter loop ends.
17
+ // 3. onEnd - checks for ANTHROPIC_API_KEY, flushes pending screenshots,
18
+ // runs SelaEngine.commitUpdates(), then prints a *non-blocking*
19
+ // write-and-notify summary (unified diff per healed file +
20
+ // vscode://file deeplink + sela-report.html deeplink). MVP flow -
21
+ // no Y/N prompt, no rollback. Mutations are already on disk by the
22
+ // time we reach this hook.
23
+ // 4. SIGINT / SIGTERM - runs gracefulShutdown() once, second signal
24
+ // hard-exits. Prevents stranded child processes from showing raw
25
+ // Node unhandledRejection stack traces on Ctrl+C.
26
+ //
27
+ // Clean Architecture: zero business logic - IO + aggregation only.
28
+ // Heal decisions live in SelaEngine, validation in ReportGenerator,
29
+ // rendering in HealReportService.
30
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ var desc = Object.getOwnPropertyDescriptor(m, k);
33
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
34
+ desc = { enumerable: true, get: function() { return m[k]; } };
35
+ }
36
+ Object.defineProperty(o, k2, desc);
37
+ }) : (function(o, m, k, k2) {
38
+ if (k2 === undefined) k2 = k;
39
+ o[k2] = m[k];
40
+ }));
41
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
42
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
43
+ }) : function(o, v) {
44
+ o["default"] = v;
45
+ });
46
+ var __importStar = (this && this.__importStar) || (function () {
47
+ var ownKeys = function(o) {
48
+ ownKeys = Object.getOwnPropertyNames || function (o) {
49
+ var ar = [];
50
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
51
+ return ar;
52
+ };
53
+ return ownKeys(o);
54
+ };
55
+ return function (mod) {
56
+ if (mod && mod.__esModule) return mod;
57
+ var result = {};
58
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
59
+ __setModuleDefault(result, mod);
60
+ return result;
61
+ };
62
+ })();
63
+ Object.defineProperty(exports, "__esModule", { value: true });
64
+ exports.SelaReporter = void 0;
65
+ const fs = __importStar(require("fs"));
66
+ const path = __importStar(require("path"));
67
+ const HealReportService_js_1 = require("../services/HealReportService.js");
68
+ const ReportMergeService_js_1 = require("../services/ReportMergeService.js");
69
+ const singleton_js_1 = require("../engine/singleton.js");
70
+ const SelaError_js_1 = require("../errors/SelaError.js");
71
+ const PendingPromptLedger_js_1 = require("../services/PendingPromptLedger.js");
72
+ const InteractiveReview_js_1 = require("../services/InteractiveReview.js");
73
+ const logger_js_1 = require("../utils/logger.js");
74
+ const SummaryTable_js_1 = require("../utils/SummaryTable.js");
75
+ // ───────────────────────────────────────────────────────────────────
76
+ // SelaReporter
77
+ // ───────────────────────────────────────────────────────────────────
78
+ class SelaReporter {
79
+ engine;
80
+ report;
81
+ logger;
82
+ skipApiKeyCheck;
83
+ cwd;
84
+ readLedger;
85
+ clearLedger;
86
+ printReview;
87
+ resolveReportPath;
88
+ isCi;
89
+ mergeShards;
90
+ shouldInstallSignalHandlers;
91
+ shutdownHandler = null;
92
+ shuttingDown = false;
93
+ /** Total tests in the suite, captured at onBegin for the end-of-run summary. */
94
+ totalTests = 0;
95
+ /**
96
+ * Screenshots that arrived before a matching FailedEvent existed in
97
+ * the shared report. Re-flushed once at onEnd time so worker-crash
98
+ * scenarios (no fixture teardown ⇒ no engine-side FailedEvent yet)
99
+ * still get their visual context attached.
100
+ *
101
+ * Key shape: `${normalisedSourceFile}::${testTitle}`.
102
+ */
103
+ pendingScreenshots = new Map();
104
+ /**
105
+ * Mirror of the failures the reporter observed, kept so external
106
+ * consumers (and tests) can audit what the reporter saw without
107
+ * having to subscribe to the entire Playwright Reporter API.
108
+ */
109
+ failures = [];
110
+ constructor(opts = {}) {
111
+ this.engine = (opts.engine ?? singleton_js_1.sharedEngine);
112
+ this.report = opts.report ?? HealReportService_js_1.sharedHealReport;
113
+ this.skipApiKeyCheck = opts.skipApiKeyCheck ?? false;
114
+ this.logger = opts.logger ?? logger_js_1.logger;
115
+ this.cwd = opts.cwd ?? process.cwd();
116
+ this.readLedger = opts.readLedger ?? PendingPromptLedger_js_1.readPendingPromptsLedger;
117
+ this.clearLedger = opts.clearLedger ?? PendingPromptLedger_js_1.clearPendingPromptsLedger;
118
+ this.printReview = opts.printReview ?? InteractiveReview_js_1.printHealReview;
119
+ this.resolveReportPath = opts.resolveReportPath ?? defaultResolveReportPath;
120
+ this.isCi = opts.isCi ?? defaultIsCi;
121
+ this.mergeShards = opts.mergeShards ?? defaultMergeShards;
122
+ this.shouldInstallSignalHandlers = opts.installSignalHandlers ?? true;
123
+ }
124
+ // ─────────────────────────────────────────────────────────────
125
+ // Playwright Reporter API
126
+ // ─────────────────────────────────────────────────────────────
127
+ onBegin(_config, suite) {
128
+ // Signal to future fixture-aware code that a reporter is driving
129
+ // finalisation. Today the fixture still calls engine.commitUpdates()
130
+ // itself; the env flag is reserved for the planned dedup guard.
131
+ process.env.SELA_REPORTER_ACTIVE = "1";
132
+ // Snapshot the suite size for the end-of-run summary table. Guarded:
133
+ // allTests() exists on real Playwright suites but not on test stubs.
134
+ try {
135
+ this.totalTests = suite?.allTests?.().length ?? 0;
136
+ }
137
+ catch {
138
+ this.totalTests = 0;
139
+ }
140
+ // SELA-5: drop any report shards stranded by a previously crashed run so
141
+ // this run's merge sees only its own workers' data.
142
+ try {
143
+ (0, HealReportService_js_1.clearReportShards)(this.cwd);
144
+ }
145
+ catch {
146
+ /* best-effort — a stale shard dir is non-fatal */
147
+ }
148
+ if (this.shouldInstallSignalHandlers) {
149
+ this.installShutdownHandler();
150
+ }
151
+ }
152
+ onTestEnd(test, result) {
153
+ if (result.status !== "failed" && result.status !== "timedOut")
154
+ return;
155
+ const sourceFile = test.location?.file ?? "";
156
+ const sourceLine = test.location?.line;
157
+ const testTitle = test.title;
158
+ const base64Png = this.extractScreenshotBase64(result);
159
+ if (base64Png) {
160
+ // First try to attach immediately - the engine may have already
161
+ // recorded the FailedEvent during fixture teardown for in-test
162
+ // heal failures. This is the happy path.
163
+ const matched = this.report.attachFailureScreenshot({ sourceFile: this.normalisePath(sourceFile), testTitle }, base64Png);
164
+ if (matched === 0) {
165
+ // No matching FailedEvent yet - buffer for the onEnd retry. This
166
+ // covers worker-crash and fixture-skip cases where the engine
167
+ // never got a chance to record the FailedEvent in-flight.
168
+ const key = this.pendingKey(sourceFile, testTitle);
169
+ this.pendingScreenshots.set(key, base64Png);
170
+ }
171
+ }
172
+ this.failures.push({
173
+ sourceFile,
174
+ sourceLine,
175
+ testTitle,
176
+ status: result.status,
177
+ hasScreenshot: !!base64Png,
178
+ });
179
+ }
180
+ async onEnd(_result) {
181
+ // Detach signal handlers first - a natural onEnd is the orderly path,
182
+ // so we don't want a late SIGINT to double-invoke shutdown logic.
183
+ this.uninstallShutdownHandler();
184
+ if (!this.skipApiKeyCheck && !process.env.ANTHROPIC_API_KEY) {
185
+ const err = new SelaError_js_1.SelaError({
186
+ subsystem: "LLMService",
187
+ code: SelaError_js_1.LLM_SERVICE_CODES.NO_API_KEY,
188
+ reason: "ANTHROPIC_API_KEY not set - SelaReporter cannot drive the heal pipeline. " +
189
+ "Set the env var (or remove the reporter entry from playwright.config.ts).",
190
+ });
191
+ // Graceful degradation: surface the error and continue flushing
192
+ // any report content the fixture path already produced.
193
+ this.logger.warn(err.message);
194
+ }
195
+ // Late-bind any screenshots that arrived before their FailedEvents.
196
+ this.flushPendingScreenshots();
197
+ // Snapshot the run tallies BEFORE commitUpdates() — it flushes the report
198
+ // to disk and then clears the in-memory event buffer.
199
+ const summary = this.collectRunSummary();
200
+ try {
201
+ await this.engine.commitUpdates();
202
+ }
203
+ catch (err) {
204
+ const msg = err instanceof Error ? err.message : String(err);
205
+ this.logger.error(`[Sela] reporter commitUpdates failed: ${msg}`);
206
+ }
207
+ // ── SELA-5: fan in per-worker heal shards ───────────────────
208
+ // Local multi-worker runs write one shard per worker (commitUpdates) to
209
+ // avoid clobbering a shared report file. The reporter is the single
210
+ // main-process writer, so it is the safe place to merge them into the
211
+ // final sela-report.{html,json}. CI uses cross-machine `sela merge`.
212
+ if (!this.isCi()) {
213
+ try {
214
+ this.mergeShards(this.cwd);
215
+ }
216
+ catch (err) {
217
+ const msg = err instanceof Error ? err.message : String(err);
218
+ this.logger.error(`[Sela] shard merge failed: ${msg}`);
219
+ }
220
+ }
221
+ // ── Local DX - Write-and-notify summary ─────────────────────
222
+ //
223
+ // Workers serialise their mutated FileSnapshots to
224
+ // `<cwd>/.sela/pending-prompts/*.json`. The reporter drains that
225
+ // ledger here and prints a non-blocking summary (diff + vscode
226
+ // deeplink + HTML report deeplink). No Y/N prompt - the files are
227
+ // already mutated on disk by the time we get here.
228
+ //
229
+ // CI runs skip the notify entirely - PR automation already handled
230
+ // the mutations on its isolated branch.
231
+ if (!this.isCi()) {
232
+ try {
233
+ const entries = this.readLedger(this.cwd);
234
+ const reportHtmlPath = this.resolveReportPath(this.cwd);
235
+ if (entries.length > 0 || reportHtmlPath) {
236
+ this.printReview({ entries, reportHtmlPath });
237
+ }
238
+ }
239
+ catch (err) {
240
+ const msg = err instanceof Error ? err.message : String(err);
241
+ this.logger.error(`[Sela] review summary failed: ${msg}`);
242
+ }
243
+ finally {
244
+ try {
245
+ this.clearLedger(this.cwd);
246
+ }
247
+ catch {
248
+ // Cleanup failures are non-fatal - the next run will overwrite.
249
+ }
250
+ }
251
+ }
252
+ else {
253
+ // CI path: drop the ledger so a follow-up local run doesn't replay
254
+ // mutations from a previous CI session.
255
+ try {
256
+ this.clearLedger(this.cwd);
257
+ }
258
+ catch {
259
+ // ignore
260
+ }
261
+ }
262
+ // End-of-run ASCII summary (skipped on a clean no-activity run).
263
+ this.renderRunSummary(summary);
264
+ }
265
+ /** Reporter prints nothing of its own - Playwright stdio stays clean. */
266
+ printsToStdio() {
267
+ return false;
268
+ }
269
+ // ─────────────────────────────────────────────────────────────
270
+ // End-of-run summary
271
+ // ─────────────────────────────────────────────────────────────
272
+ /**
273
+ * Tally the run's outcome from the report buffer. MUST be called before
274
+ * commitUpdates() clears the in-memory events. "Errors detected" counts
275
+ * every broken selector Sela engaged (healed + held + failed); "skipped"
276
+ * counts heals declined by a developer fail-fast directive.
277
+ */
278
+ collectRunSummary() {
279
+ const healed = this.report.getHealedEvents().length;
280
+ const held = this.report.getProtectedEvents().length;
281
+ const failedEvents = this.report.getFailedEvents();
282
+ const skipped = failedEvents.filter((e) => typeof e.reason === "string" &&
283
+ e.reason.startsWith("Skipped by Developer")).length;
284
+ return {
285
+ testsScanned: this.totalTests,
286
+ errorsDetected: healed + held + failedEvents.length,
287
+ successfulHeals: healed,
288
+ skippedFiles: skipped,
289
+ };
290
+ }
291
+ /**
292
+ * Render the summary table — but only when Sela actually did something.
293
+ * A run with zero detected errors prints nothing, keeping the terminal
294
+ * clean for the common all-green case.
295
+ */
296
+ renderRunSummary(summary) {
297
+ if (summary.errorsDetected === 0)
298
+ return;
299
+ this.logger.info("\nSela run summary:");
300
+ this.logger.info((0, SummaryTable_js_1.renderSummaryTable)(summary));
301
+ }
302
+ // ─────────────────────────────────────────────────────────────
303
+ // Graceful shutdown - SIGINT / SIGTERM
304
+ // ─────────────────────────────────────────────────────────────
305
+ /**
306
+ * Install the SIGINT/SIGTERM listener once per reporter. First signal
307
+ * triggers an orderly drain; second signal hard-exits with code 130
308
+ * (SIGINT) / 143 (SIGTERM) so the user can always escape if the drain
309
+ * itself wedges (e.g. a stuck LLM call).
310
+ */
311
+ installShutdownHandler() {
312
+ if (this.shutdownHandler)
313
+ return;
314
+ const handler = (signal) => {
315
+ if (this.shuttingDown) {
316
+ process.stderr.write(`\n[Sela] ⏹ Force exit on second ${signal}.\n`);
317
+ process.exit(signal === "SIGTERM" ? 143 : 130);
318
+ return;
319
+ }
320
+ this.shuttingDown = true;
321
+ process.stderr.write(`\n[Sela] 🛑 ${signal} received - flushing state and shutting down...\n`);
322
+ this.gracefulShutdown()
323
+ .catch((err) => {
324
+ const msg = err instanceof Error ? err.message : String(err);
325
+ process.stderr.write(`[Sela] Shutdown error: ${msg}\n`);
326
+ })
327
+ .finally(() => {
328
+ process.stderr.write(`[Sela] 👋 Goodbye.\n`);
329
+ process.exit(signal === "SIGTERM" ? 143 : 130);
330
+ });
331
+ };
332
+ this.shutdownHandler = handler;
333
+ process.on("SIGINT", handler);
334
+ process.on("SIGTERM", handler);
335
+ }
336
+ uninstallShutdownHandler() {
337
+ if (!this.shutdownHandler)
338
+ return;
339
+ process.off("SIGINT", this.shutdownHandler);
340
+ process.off("SIGTERM", this.shutdownHandler);
341
+ this.shutdownHandler = null;
342
+ }
343
+ /**
344
+ * Best-effort drain on signal. Mirrors the orderly onEnd path but
345
+ * swallows every error - we never want to throw inside a signal
346
+ * handler because Node prints raw stack traces otherwise.
347
+ *
348
+ * Exposed for tests so they can drive the shutdown without raising
349
+ * a real signal in the vitest process.
350
+ */
351
+ async gracefulShutdown() {
352
+ try {
353
+ this.flushPendingScreenshots();
354
+ }
355
+ catch {
356
+ // ignore
357
+ }
358
+ try {
359
+ await this.engine.commitUpdates();
360
+ }
361
+ catch {
362
+ // ignore
363
+ }
364
+ try {
365
+ const entries = this.isCi() ? [] : this.readLedger(this.cwd);
366
+ const reportHtmlPath = this.resolveReportPath(this.cwd);
367
+ if (entries.length > 0 || reportHtmlPath) {
368
+ this.printReview({ entries, reportHtmlPath });
369
+ }
370
+ }
371
+ catch {
372
+ // ignore
373
+ }
374
+ try {
375
+ this.clearLedger(this.cwd);
376
+ }
377
+ catch {
378
+ // ignore
379
+ }
380
+ }
381
+ // ─────────────────────────────────────────────────────────────
382
+ // Internals (exposed for testing - prefixed underscore is the
383
+ // convention used elsewhere in the codebase for proxy back-doors).
384
+ // ─────────────────────────────────────────────────────────────
385
+ /**
386
+ * Walk every buffered pending screenshot and try to attach it to a
387
+ * now-existing FailedEvent. Successfully-attached entries are
388
+ * removed; unmatched entries are dropped (the matching FailedEvent
389
+ * never arrived - most likely worker crashed before the engine
390
+ * could record one).
391
+ *
392
+ * Returns the number of FailedEvents touched.
393
+ */
394
+ flushPendingScreenshots() {
395
+ let total = 0;
396
+ for (const [key, base64] of Array.from(this.pendingScreenshots.entries())) {
397
+ const sepIndex = key.indexOf("::");
398
+ if (sepIndex < 0) {
399
+ this.pendingScreenshots.delete(key);
400
+ continue;
401
+ }
402
+ const filePart = key.slice(0, sepIndex);
403
+ const titlePart = key.slice(sepIndex + 2);
404
+ const matched = this.report.attachFailureScreenshot({ sourceFile: filePart, testTitle: titlePart }, base64);
405
+ if (matched > 0) {
406
+ total += matched;
407
+ this.pendingScreenshots.delete(key);
408
+ }
409
+ }
410
+ return total;
411
+ }
412
+ /** Test hook - read-only snapshot of recorded failures. */
413
+ getRecordedFailures() {
414
+ return this.failures.slice();
415
+ }
416
+ /** Test hook - number of screenshots still waiting for a FailedEvent. */
417
+ getPendingScreenshotCount() {
418
+ return this.pendingScreenshots.size;
419
+ }
420
+ // ─────────────────────────────────────────────────────────────
421
+ // Private helpers
422
+ // ─────────────────────────────────────────────────────────────
423
+ pendingKey(sourceFile, testTitle) {
424
+ return `${this.normalisePath(sourceFile)}::${testTitle}`;
425
+ }
426
+ normalisePath(p) {
427
+ if (!p)
428
+ return "";
429
+ try {
430
+ const abs = path.isAbsolute(p) ? p : path.resolve(process.cwd(), p);
431
+ const rel = path.relative(process.cwd(), abs);
432
+ return (rel || abs).split("\\").join("/");
433
+ }
434
+ catch {
435
+ return p.split("\\").join("/");
436
+ }
437
+ }
438
+ /**
439
+ * Convert the first PNG attachment on a TestResult into a Base64
440
+ * string immediately. Prefers an in-memory `body` when Playwright
441
+ * already inlined the bytes (faster, no IO); falls back to reading
442
+ * the attachment `path` synchronously BEFORE Playwright has a chance
443
+ * to clean up its temp folder.
444
+ */
445
+ extractScreenshotBase64(result) {
446
+ const attachments = result.attachments ?? [];
447
+ for (const att of attachments) {
448
+ const contentType = (att.contentType ?? "").toLowerCase();
449
+ const looksLikePng = contentType.includes("png") ||
450
+ (att.name ?? "").toLowerCase().includes("screenshot") ||
451
+ (att.path ?? "").toLowerCase().endsWith(".png");
452
+ if (!looksLikePng)
453
+ continue;
454
+ // Playwright >= 1.46 sometimes inlines the body for small images.
455
+ const inline = att.body;
456
+ if (inline && inline.length > 0) {
457
+ return Buffer.isBuffer(inline)
458
+ ? inline.toString("base64")
459
+ : Buffer.from(inline).toString("base64");
460
+ }
461
+ if (att.path) {
462
+ try {
463
+ const bytes = fs.readFileSync(att.path);
464
+ return bytes.toString("base64");
465
+ }
466
+ catch {
467
+ // Temp file already gone - nothing we can do.
468
+ }
469
+ }
470
+ }
471
+ return undefined;
472
+ }
473
+ }
474
+ exports.SelaReporter = SelaReporter;
475
+ /**
476
+ * Mirror of the CI detection used by `SelaEngine.commitUpdates()`.
477
+ * Accepts the standard `CI=1`/`CI=true` convention; everything else
478
+ * (empty string, undefined, `0`, `false`) is Local DX mode.
479
+ */
480
+ function defaultIsCi() {
481
+ const raw = process.env.CI;
482
+ if (raw === undefined || raw === null)
483
+ return false;
484
+ const v = String(raw).trim().toLowerCase();
485
+ return v !== "" && v !== "0" && v !== "false";
486
+ }
487
+ /**
488
+ * Default HTML report locator. Returns the absolute path when
489
+ * `<cwd>/sela-report.html` exists on disk after `commitUpdates()` has
490
+ * had its chance to flush, otherwise null so the printer can skip the
491
+ * "Insights report:" footer entirely.
492
+ */
493
+ function defaultResolveReportPath(cwd) {
494
+ const candidate = path.join(cwd, "sela-report.html");
495
+ return fs.existsSync(candidate) ? candidate : null;
496
+ }
497
+ /**
498
+ * Default shard fan-in (SELA-5). Discovers this run's per-worker shards under
499
+ * `<cwd>/.sela/report-shards/` and merges them into the final
500
+ * sela-report.{html,json} + rolling history via ReportMergeService, then clears
501
+ * the shard dir. A no-op when no shards exist (single-process / no-heal runs),
502
+ * so it is safe to call unconditionally on every local run.
503
+ */
504
+ function defaultMergeShards(cwd) {
505
+ const shardFiles = ReportMergeService_js_1.ReportMergeService.discoverShardFiles((0, HealReportService_js_1.reportShardDir)(cwd), "sela-shard-*.json");
506
+ if (shardFiles.length === 0)
507
+ return;
508
+ try {
509
+ ReportMergeService_js_1.ReportMergeService.merge({ shardFiles, targetDir: cwd });
510
+ }
511
+ finally {
512
+ (0, HealReportService_js_1.clearReportShards)(cwd);
513
+ }
514
+ }
515
+ // Default export so Playwright can resolve `reporter: [['sela-core/reporter']]`
516
+ // without needing the consumer to spell out the named import.
517
+ exports.default = SelaReporter;
@@ -0,0 +1,143 @@
1
+ import { SelectorSegment } from "./LLMService";
2
+ import { AdvisoryBuffer } from "./HealingAdvisory";
3
+ import type { SmartChainSegment } from "./LLMService";
4
+ import { TraceOutcome } from "./TraceBackEngine";
5
+ import { Decision } from "./DecisionEngine";
6
+ import { FileBatch, ApplyOutcome, ApplyOptions } from "./MutationApplier";
7
+ export interface ASTUpdateResult {
8
+ success: boolean;
9
+ reason: string;
10
+ strategy: string;
11
+ lineUpdated?: number;
12
+ cascadeFixed?: number;
13
+ /** The normalized locator string that was written to disk. Single source of truth for runtime. */
14
+ healedLocatorString?: string;
15
+ /** Populated by semantic dispatch: where the definition was mutated. */
16
+ definitionSite?: {
17
+ file: string;
18
+ line: number;
19
+ };
20
+ /** Number of test functions referencing the mutated constant (blast radius). */
21
+ blastRadius?: number;
22
+ }
23
+ interface CallerContext {
24
+ filePath: string;
25
+ line: number;
26
+ }
27
+ export interface ComposeHealInput {
28
+ filePath: string;
29
+ /** 1-based line of the failing call-site. */
30
+ line: number;
31
+ /** 0-based column; when omitted the first non-whitespace char of the line is used. */
32
+ column?: number;
33
+ /**
34
+ * Healed locator EXPRESSION text, e.g. `page.locator(".btn-v2")`. When
35
+ * omitted, it is BUILT from `newSelector` + the traced target's root
36
+ * receiver (internal selectors → idiomatic method form).
37
+ */
38
+ newLocatorExpr?: string;
39
+ /** Raw healed selector string (may be an `internal:` engine selector). */
40
+ newSelector?: string;
41
+ /** Runtime: only the failing test needs the new selector. */
42
+ contextSpecific?: boolean;
43
+ /** Runtime: selector rot is global across all consumers. */
44
+ globalCorrect?: boolean;
45
+ /** When true, write the result via MutationApplier (with the gate). */
46
+ apply?: boolean;
47
+ applyOptions?: ApplyOptions;
48
+ }
49
+ export interface ComposeHealResult {
50
+ kind: "decision" | "abort";
51
+ trace: TraceOutcome;
52
+ decision?: Decision;
53
+ batch?: FileBatch;
54
+ outcome?: ApplyOutcome;
55
+ /** 1-based line of the mutated target node (for report/diff). */
56
+ writtenLine?: number;
57
+ }
58
+ export declare class ASTSourceUpdater {
59
+ private project;
60
+ readonly advisoryBuffer: AdvisoryBuffer;
61
+ flushAdvisories(): void;
62
+ /**
63
+ * Trace the failing call-site back to its source declaration, decide the
64
+ * mutation strategy (in-place / fork / prompt), and — when `apply` is set —
65
+ * write it to disk through the type-safety gate.
66
+ */
67
+ static composeHeal(input: ComposeHealInput): ComposeHealResult;
68
+ /** Drain-loop entry: apply pre-built batches through the write gate. */
69
+ static applyMutationBatches(batches: FileBatch[], opts?: ApplyOptions): ApplyOutcome[];
70
+ /** Convert a DecisionEngine result into an anchored MutationApplier batch. */
71
+ static decisionToBatch(filePath: string, decision: Decision): FileBatch;
72
+ /**
73
+ * Centralised write hook for every ts-morph `saveSync` call in this class.
74
+ * When `SELA_DRY_RUN` is active the AST mutation stays in memory but the
75
+ * on-disk file is left untouched - the heal pipeline can still compute a
76
+ * candidate diff via `sourceFile.getFullText()` and the report layer
77
+ * tags the event with `dryRun: true`.
78
+ */
79
+ private _persistChanges;
80
+ scanFailFastDirective(caller: CallerContext): {
81
+ failFast: boolean;
82
+ matchedComment?: string;
83
+ matchedLine?: number;
84
+ };
85
+ /**
86
+ * Convenience helper - runs `scanFailFastDirective` and throws the
87
+ * canonical SelaError when the directive is present. Used by SelaEngine
88
+ * as the very first gate inside `heal()`.
89
+ */
90
+ enforceFailFastDirective(caller: CallerContext): void;
91
+ constructor();
92
+ private readonly WRAPPER_IDENTIFIERS;
93
+ private readonly STRUCTURAL_ROLES;
94
+ private readonly INTERACTIVE_ROLES;
95
+ update(caller: CallerContext, oldSelector: string, newSelector: string, aiSegments?: SelectorSegment[], fullSelectorContext?: string, contentChange?: {
96
+ oldText: string;
97
+ newText: string;
98
+ }, smartChainSegments?: SmartChainSegment[], originalChainHint?: SmartChainSegment[]): ASTUpdateResult;
99
+ private strategySmartChain;
100
+ private attemptPartialChainHeal;
101
+ private strategyChainCollapse;
102
+ private runStrategyG;
103
+ private strategyFrameUpstream;
104
+ private strategyDeepSymbolResolution;
105
+ private strategyInlineSemanticFix;
106
+ private strategyTemplateLiteral;
107
+ private strategySemanticFragmentScan;
108
+ private findMatchingChainTail;
109
+ private replaceChainTailOnly;
110
+ private applySemanticFix;
111
+ /**
112
+ * Guard: returns false when replacing oldNode with proposedNewText would
113
+ * substitute a hardcoded string literal for an Identifier or
114
+ * PropertyAccessExpression - which is the definition-site mutation bug.
115
+ * All other replacements are allowed.
116
+ */
117
+ private static isSafeReplacement;
118
+ private replaceCallArgument;
119
+ private semanticToInternal;
120
+ private performCascadeHeal;
121
+ private fixPropertyAccessDefinition;
122
+ private isBlockedByStructuralWall;
123
+ private identifySuspectIdentifier;
124
+ private getEnclosingStatement;
125
+ private findNodeAtLine;
126
+ private findCallExpressionsInRange;
127
+ private replaceFrameLocatorArg;
128
+ private replaceStringLiteralInRange;
129
+ private updateObjectProperty;
130
+ private lineToOffset;
131
+ resolveFilePath(raw: string): string | null;
132
+ private semanticDispatch;
133
+ private applyDefinitionSiteHeal;
134
+ private handleIdentifierArg;
135
+ private handlePropertyAccessArg;
136
+ private handleTemplateLiteralArg;
137
+ private traceSpanExpression;
138
+ private handleCallExpressionArg;
139
+ private validateFileSyntax;
140
+ private broadcastAndReturn;
141
+ }
142
+ export {};
143
+ //# sourceMappingURL=ASTSourceUpdater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ASTSourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/ASTSourceUpdater.ts"],"names":[],"mappings":"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"}