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,51 @@
1
+ import type { WorkspaceSnapshotService } from "./WorkspaceSnapshotService";
2
+ import type { HealedEvent } from "./HealReportService";
3
+ export interface PendingPromptEntry {
4
+ absolutePath: string;
5
+ relativePath: string;
6
+ contentBefore: string;
7
+ contentAfter: string;
8
+ createdBySela: boolean;
9
+ /** 1-based line number for the vscode:// deeplink, or null when unknown. */
10
+ lineNumber: number | null;
11
+ /**
12
+ * Number of healed selectors that landed in THIS file. A single file can
13
+ * absorb several heals in one run (e.g. two locators in the same spec), so
14
+ * the DX banner counts fixes from this field rather than from the entry
15
+ * (= file) count. Older ledgers without the field are treated as 1.
16
+ */
17
+ healCount: number;
18
+ }
19
+ /**
20
+ * Resolve the ledger directory for a given cwd. The directory is created
21
+ * lazily on the first write so we never clutter repos that aren't running
22
+ * Sela.
23
+ */
24
+ export declare function ledgerDir(cwd: string): string;
25
+ /**
26
+ * Persist this worker's mutated snapshots to a fresh JSON file under
27
+ * `<cwd>/.sela/pending-prompts/`. Idempotent within a single worker -
28
+ * subsequent calls in the same process append a NEW file (rare in
29
+ * practice but keeps the contract simple).
30
+ *
31
+ * Returns the absolute path of the written file, or `null` when there is
32
+ * nothing to persist (so callers can skip the prompt entirely in CI /
33
+ * empty-mutation runs).
34
+ */
35
+ export declare function writePendingPromptsLedger(opts: {
36
+ cwd: string;
37
+ workspace: WorkspaceSnapshotService;
38
+ healedEvents: HealedEvent[];
39
+ }): string | null;
40
+ /**
41
+ * Drain every per-worker JSON file under the ledger directory and merge
42
+ * their entries into a single de-duplicated list (keyed by absolutePath).
43
+ * The most-recent contentAfter wins on collision - that's the disk truth.
44
+ *
45
+ * The directory is NOT deleted here so the reporter can inspect entries
46
+ * before calling `clearPendingPromptsLedger()`.
47
+ */
48
+ export declare function readPendingPromptsLedger(cwd: string): PendingPromptEntry[];
49
+ /** Remove the ledger directory and every file beneath it. Idempotent. */
50
+ export declare function clearPendingPromptsLedger(cwd: string): void;
51
+ //# sourceMappingURL=PendingPromptLedger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PendingPromptLedger.d.ts","sourceRoot":"","sources":["../../src/services/PendingPromptLedger.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAEV,wBAAwB,EACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAID;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,wBAAwB,CAAC;IACpC,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B,GAAG,MAAM,GAAG,IAAI,CAehB;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAyB1E;AAED,yEAAyE;AACzE,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAI3D"}
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ // src/services/PendingPromptLedger.ts
3
+ //
4
+ // Cross-process ledger for the Local DX dual-mode lifecycle.
5
+ //
6
+ // Playwright workers run in separate Node processes from the reporter
7
+ // (main process). The in-memory `WorkspaceSnapshotService` ledger is
8
+ // per-process, so we can't drive an interactive prompt from the reporter
9
+ // using only worker-side state.
10
+ //
11
+ // Solution: each worker SERIALISES its mutated FileSnapshots to a JSON
12
+ // file under `<cwd>/.sela/pending-prompts/`, one file per worker process
13
+ // (keyed by pid + monotonic timestamp). The reporter's onEnd hook reads
14
+ // every file in that directory, prints a non-blocking summary via
15
+ // `printHealReview()`, then deletes the directory.
16
+ //
17
+ // CRITICAL: workers MUST NOT call `readline` / block on stdin - they have
18
+ // no TTY attached. Blocking the event loop here causes the Playwright
19
+ // test timeout to fire. This ledger is the boundary between silent
20
+ // worker-side execution and TTY-bound reporter-side prompting.
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.ledgerDir = ledgerDir;
56
+ exports.writePendingPromptsLedger = writePendingPromptsLedger;
57
+ exports.readPendingPromptsLedger = readPendingPromptsLedger;
58
+ exports.clearPendingPromptsLedger = clearPendingPromptsLedger;
59
+ const fs = __importStar(require("fs"));
60
+ const path = __importStar(require("path"));
61
+ const LEDGER_SUBDIR = path.join(".sela", "pending-prompts");
62
+ /**
63
+ * Resolve the ledger directory for a given cwd. The directory is created
64
+ * lazily on the first write so we never clutter repos that aren't running
65
+ * Sela.
66
+ */
67
+ function ledgerDir(cwd) {
68
+ return path.join(cwd, LEDGER_SUBDIR);
69
+ }
70
+ /**
71
+ * Persist this worker's mutated snapshots to a fresh JSON file under
72
+ * `<cwd>/.sela/pending-prompts/`. Idempotent within a single worker -
73
+ * subsequent calls in the same process append a NEW file (rare in
74
+ * practice but keeps the contract simple).
75
+ *
76
+ * Returns the absolute path of the written file, or `null` when there is
77
+ * nothing to persist (so callers can skip the prompt entirely in CI /
78
+ * empty-mutation runs).
79
+ */
80
+ function writePendingPromptsLedger(opts) {
81
+ const snaps = opts.workspace.getMutatedSnapshots();
82
+ if (snaps.length === 0)
83
+ return null;
84
+ const entries = snaps.map((s) => snapshotToEntry(s, opts.healedEvents, opts.cwd));
85
+ const dir = ledgerDir(opts.cwd);
86
+ fs.mkdirSync(dir, { recursive: true });
87
+ const fileName = `${process.pid}-${Date.now()}-${randomTag()}.json`;
88
+ const full = path.join(dir, fileName);
89
+ fs.writeFileSync(full, JSON.stringify(entries, null, 2), "utf8");
90
+ return full;
91
+ }
92
+ /**
93
+ * Drain every per-worker JSON file under the ledger directory and merge
94
+ * their entries into a single de-duplicated list (keyed by absolutePath).
95
+ * The most-recent contentAfter wins on collision - that's the disk truth.
96
+ *
97
+ * The directory is NOT deleted here so the reporter can inspect entries
98
+ * before calling `clearPendingPromptsLedger()`.
99
+ */
100
+ function readPendingPromptsLedger(cwd) {
101
+ const dir = ledgerDir(cwd);
102
+ if (!fs.existsSync(dir))
103
+ return [];
104
+ const merged = new Map();
105
+ const files = fs
106
+ .readdirSync(dir)
107
+ .filter((f) => f.endsWith(".json"))
108
+ .sort(); // pid-timestamp prefix gives a stable, time-ordered merge
109
+ for (const f of files) {
110
+ const full = path.join(dir, f);
111
+ try {
112
+ const raw = fs.readFileSync(full, "utf8");
113
+ const parsed = JSON.parse(raw);
114
+ if (!Array.isArray(parsed))
115
+ continue;
116
+ for (const entry of parsed) {
117
+ if (!entry || typeof entry.absolutePath !== "string")
118
+ continue;
119
+ merged.set(path.normalize(entry.absolutePath), entry);
120
+ }
121
+ }
122
+ catch {
123
+ // Corrupt ledger file - skip rather than crashing the whole review.
124
+ }
125
+ }
126
+ return Array.from(merged.values());
127
+ }
128
+ /** Remove the ledger directory and every file beneath it. Idempotent. */
129
+ function clearPendingPromptsLedger(cwd) {
130
+ const dir = ledgerDir(cwd);
131
+ if (!fs.existsSync(dir))
132
+ return;
133
+ fs.rmSync(dir, { recursive: true, force: true });
134
+ }
135
+ // ───────────────────────────────────────────────────────────────────
136
+ // Helpers
137
+ // ───────────────────────────────────────────────────────────────────
138
+ function snapshotToEntry(snap, heals, cwd) {
139
+ return {
140
+ absolutePath: snap.absolutePath,
141
+ relativePath: snap.relativePath,
142
+ contentBefore: snap.contentBefore,
143
+ contentAfter: snap.contentAfter ?? "",
144
+ createdBySela: snap.createdBySela,
145
+ lineNumber: findLineNumberForSnapshot(snap, heals, cwd),
146
+ healCount: countHealsForSnapshot(snap, heals, cwd),
147
+ };
148
+ }
149
+ /**
150
+ * Count how many heals mutated `snap`. A heal's mutation target is its
151
+ * `definitionSite.file` when the write crossed into a const/variable
152
+ * declaration, otherwise its `sourceFile`. Resolved to absolute form so a
153
+ * relative event path matches the snapshot's absolute path.
154
+ *
155
+ * Falls back to 1 when no heal resolves to the file - the snapshot only
156
+ * exists because Sela wrote to it, so the file represents at least one fix.
157
+ */
158
+ function countHealsForSnapshot(snap, heals, cwd) {
159
+ const normSnap = path.normalize(snap.absolutePath);
160
+ let n = 0;
161
+ for (const heal of heals) {
162
+ const target = heal.definitionSite?.file ?? heal.sourceFile;
163
+ if (!target)
164
+ continue;
165
+ const abs = path.isAbsolute(target)
166
+ ? path.normalize(target)
167
+ : path.normalize(path.resolve(cwd, target));
168
+ if (abs === normSnap)
169
+ n++;
170
+ }
171
+ return n > 0 ? n : 1;
172
+ }
173
+ /**
174
+ * Resolve a 1-based line number for the vscode:// deeplink. Priority:
175
+ * 1. `definitionSite.line` for a heal whose `definitionSite.file`
176
+ * resolves to this snapshot.
177
+ * 2. `newLineNumber` reported on a heal whose `sourceFile` resolves to
178
+ * this snapshot.
179
+ * 3. `null` (link emitted without a line suffix).
180
+ */
181
+ function findLineNumberForSnapshot(snap, heals, cwd) {
182
+ const normSnap = path.normalize(snap.absolutePath);
183
+ for (const heal of heals) {
184
+ if (heal.definitionSite) {
185
+ const defAbs = path.isAbsolute(heal.definitionSite.file)
186
+ ? path.normalize(heal.definitionSite.file)
187
+ : path.normalize(path.resolve(cwd, heal.definitionSite.file));
188
+ if (defAbs === normSnap && heal.definitionSite.line > 0) {
189
+ return heal.definitionSite.line;
190
+ }
191
+ }
192
+ }
193
+ for (const heal of heals) {
194
+ const healAbs = path.isAbsolute(heal.sourceFile)
195
+ ? path.normalize(heal.sourceFile)
196
+ : path.normalize(path.resolve(cwd, heal.sourceFile));
197
+ if (healAbs === normSnap && heal.newLineNumber > 0) {
198
+ return heal.newLineNumber;
199
+ }
200
+ }
201
+ return null;
202
+ }
203
+ function randomTag() {
204
+ return Math.random().toString(36).slice(2, 8);
205
+ }
@@ -0,0 +1,156 @@
1
+ import type { HealEvent, HealEventKind } from "./HealReportService";
2
+ export declare const TIME_SAVED_CONSTANTS: {
3
+ /** A healed selector saved an engineer from manually hunting + patching. */
4
+ readonly PER_HEAL: 12;
5
+ /**
6
+ * Catching a masked regression is worth more — it would have silently
7
+ * changed test semantics and required a full debugging cycle to uncover.
8
+ */
9
+ readonly PER_PROTECT: 18;
10
+ /**
11
+ * Partial value: Sela narrowed the debug scope even when it couldn't fix.
12
+ */
13
+ readonly PER_FAILED: 4;
14
+ };
15
+ /**
16
+ * Persisted after every run. Kept in a rolling window of up to 14 entries
17
+ * by HealReportService. Used to render the Management trend chart.
18
+ *
19
+ * **Backend addition required:** HealReportService.flushToDisk() reads
20
+ * `.sela-history.json`, appends the result of
21
+ * `ReportGenerator.buildCurrentHistoricalRun()`, trims to 14 entries, writes
22
+ * it back, and passes the array into `ReportGenerator.generate()`.
23
+ */
24
+ export interface HistoricalRun {
25
+ /** Stable identifier — defaults to ISO timestamp but can be CI run ID. */
26
+ id: string;
27
+ /** Human-readable x-axis label shown in the trend chart (e.g. "Jan 15"). */
28
+ label: string;
29
+ healed: number;
30
+ protected: number;
31
+ failed: number;
32
+ /**
33
+ * Mean `aiConfidence` across all events in the run (0–100).
34
+ * Computed by `buildCurrentHistoricalRun()`.
35
+ * 0 when no events carried a confidence value.
36
+ */
37
+ avg_confidence: number;
38
+ /** Estimated developer minutes saved this run. */
39
+ time_saved_min: number;
40
+ /** ISO 8601 — used for deduplication and display sorting. */
41
+ timestamp: string;
42
+ }
43
+ export interface RoiMetrics {
44
+ /**
45
+ * Estimated minutes of developer time saved in THIS run.
46
+ * Mirrors stats.timeSavedMin — kept here so callers don't need to import
47
+ * both interfaces.
48
+ */
49
+ timeSavedThisRunMin: number;
50
+ /**
51
+ * Cumulative minutes saved across all historical runs (including current).
52
+ * The Management Dashboard renders this as "Total Time Saved This Month"
53
+ * when the history window covers ~30 days.
54
+ */
55
+ timeSavedCumulativeMin: number;
56
+ /**
57
+ * Number of PROTECTED events in this run.
58
+ * Each represents a regression that would have silently mutated test
59
+ * semantics had Sela auto-applied the AI fix.
60
+ */
61
+ bugsPrevented: number;
62
+ /**
63
+ * Percentage of all healing attempts (HEALED + PROTECTED) where the
64
+ * Intent Auditor's final confidence was ≥ 80. Rendered as the
65
+ * "High Confidence Rate" KPI in the Management view.
66
+ * `null` when there are no audited events.
67
+ */
68
+ highConfidenceRatePct: number | null;
69
+ /**
70
+ * Mean aiConfidence across HEALED events only (0–100).
71
+ * `null` when there are no healed events with a confidence value.
72
+ */
73
+ avgHealConfidence: number | null;
74
+ }
75
+ export interface ReportStats {
76
+ total: number;
77
+ healed: number;
78
+ failed: number;
79
+ protectedCnt: number;
80
+ iframeCnt: number;
81
+ shadowCnt: number;
82
+ /** Estimated developer minutes saved this run. */
83
+ timeSavedMin: number;
84
+ }
85
+ export interface ReportData {
86
+ generatedAt: string;
87
+ startedAt: string;
88
+ cwd: string;
89
+ events: HealEvent[];
90
+ stats: ReportStats;
91
+ roi: RoiMetrics;
92
+ /**
93
+ * Rolling window of up to 14 runs injected from `.sela-history.json`.
94
+ * Empty array when no history file exists yet (first run).
95
+ */
96
+ historical_runs: HistoricalRun[];
97
+ }
98
+ export declare const MANDATORY_FIELDS_BY_KIND: Readonly<Record<HealEventKind, ReadonlyArray<string>>>;
99
+ export declare class ReportGenerator {
100
+ /**
101
+ * Validates a single event against MANDATORY_FIELDS_BY_KIND.
102
+ * Throws a SelaError(subsystem="Report") on the first violation.
103
+ */
104
+ static validateEvent(event: unknown): asserts event is HealEvent;
105
+ /**
106
+ * Validates every event in the buffer. Returns the typed array when all
107
+ * events pass. Throws on the first violation.
108
+ */
109
+ static validateAll(events: ReadonlyArray<unknown>): HealEvent[];
110
+ /**
111
+ * Pure aggregate counters. No clock, no IO — trivially pinnable in tests.
112
+ */
113
+ static computeStats(events: ReadonlyArray<HealEvent>): ReportStats;
114
+ /**
115
+ * Derives Management Dashboard KPIs from the event buffer + historical runs.
116
+ *
117
+ * `historicalRuns` should already include the current run if you want
118
+ * cumulative totals to include this run — pass the array AFTER appending
119
+ * via `buildCurrentHistoricalRun()`.
120
+ */
121
+ static computeRoiMetrics(events: ReadonlyArray<HealEvent>, historicalRuns: ReadonlyArray<HistoricalRun>, stats: ReportStats): RoiMetrics;
122
+ /**
123
+ * Builds the `HistoricalRun` entry for the current run so the caller can
124
+ * append it to the persisted sidecar file.
125
+ *
126
+ * `runId` — optional override; defaults to ISO timestamp. Pass a CI run ID
127
+ * (e.g. `process.env.GITHUB_RUN_ID`) when available so deduplication is
128
+ * reliable across retries.
129
+ */
130
+ static buildCurrentHistoricalRun(events: ReadonlyArray<HealEvent>, stats: ReportStats, opts?: {
131
+ runId?: string;
132
+ now?: () => Date;
133
+ }): HistoricalRun;
134
+ /**
135
+ * Validates every event, computes all metrics, and assembles the
136
+ * `ReportData` payload ready for serialisation.
137
+ *
138
+ * `historicalRuns` — pass the array from `.sela-history.json` BEFORE
139
+ * appending the current run; this method appends it internally so the
140
+ * trend chart always includes the present run.
141
+ */
142
+ static generate(events: ReadonlyArray<unknown>, opts?: {
143
+ cwd?: string;
144
+ startedAt?: string;
145
+ historicalRuns?: HistoricalRun[];
146
+ runId?: string;
147
+ now?: () => Date;
148
+ }): ReportData;
149
+ /**
150
+ * Format a confidence value for UI consumption.
151
+ * Returns a percentage string ("87%") for finite numbers, "n/a" for
152
+ * anything else. NEVER emits literal "undefined" / "null" / "NaN".
153
+ */
154
+ static formatConfidence(value: unknown): string;
155
+ }
156
+ //# sourceMappingURL=ReportGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReportGenerator.d.ts","sourceRoot":"","sources":["../../src/services/ReportGenerator.ts"],"names":[],"mappings":"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"}