sela-core 1.0.7 → 1.0.9

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 (146) hide show
  1. package/README.md +27 -17
  2. package/dist/cli/ErrorHandler.d.ts +1 -1
  3. package/dist/cli/ErrorHandler.js +14 -14
  4. package/dist/cli/commands/bulk.d.ts +1 -1
  5. package/dist/cli/commands/bulk.d.ts.map +1 -1
  6. package/dist/cli/commands/bulk.js +51 -33
  7. package/dist/cli/commands/init.d.ts +1 -1
  8. package/dist/cli/commands/init.d.ts.map +1 -1
  9. package/dist/cli/commands/init.js +26 -18
  10. package/dist/cli/commands/merge.d.ts +13 -0
  11. package/dist/cli/commands/merge.d.ts.map +1 -0
  12. package/dist/cli/commands/merge.js +119 -0
  13. package/dist/cli/commands/showReport.d.ts +1 -1
  14. package/dist/cli/commands/showReport.d.ts.map +1 -1
  15. package/dist/cli/commands/showReport.js +12 -10
  16. package/dist/cli/commands/status.d.ts +1 -1
  17. package/dist/cli/commands/status.d.ts.map +1 -1
  18. package/dist/cli/commands/status.js +8 -8
  19. package/dist/cli/commands/sync.d.ts +1 -1
  20. package/dist/cli/commands/sync.d.ts.map +1 -1
  21. package/dist/cli/commands/sync.js +38 -30
  22. package/dist/cli/index.js +12 -9
  23. package/dist/cli/ui/DnaTable.d.ts +1 -1
  24. package/dist/cli/ui/DnaTable.d.ts.map +1 -1
  25. package/dist/cli/ui/DnaTable.js +23 -16
  26. package/dist/cli/ui/RefactorWizard.d.ts +3 -3
  27. package/dist/cli/ui/RefactorWizard.d.ts.map +1 -1
  28. package/dist/cli/ui/RefactorWizard.js +108 -82
  29. package/dist/config/ConfigLoader.d.ts +2 -2
  30. package/dist/config/ConfigLoader.d.ts.map +1 -1
  31. package/dist/config/ConfigLoader.js +15 -15
  32. package/dist/config/DryRunGuard.d.ts +1 -1
  33. package/dist/config/DryRunGuard.js +7 -7
  34. package/dist/config/SelaConfig.d.ts +13 -17
  35. package/dist/config/SelaConfig.d.ts.map +1 -1
  36. package/dist/config/SelaConfig.js +32 -26
  37. package/dist/engine/HealingRegistry.d.ts +1 -1
  38. package/dist/engine/HealingRegistry.js +3 -3
  39. package/dist/engine/SelaEngine.d.ts +1 -1
  40. package/dist/engine/SelaEngine.d.ts.map +1 -1
  41. package/dist/engine/SelaEngine.js +117 -51
  42. package/dist/errors/SelaError.d.ts +8 -1
  43. package/dist/errors/SelaError.d.ts.map +1 -1
  44. package/dist/errors/SelaError.js +14 -7
  45. package/dist/fixtures/expectProxy.d.ts +2 -2
  46. package/dist/fixtures/expectProxy.js +16 -16
  47. package/dist/fixtures/index.d.ts +18 -2
  48. package/dist/fixtures/index.d.ts.map +1 -1
  49. package/dist/fixtures/index.js +47 -27
  50. package/dist/fixtures/moduleExpect.js +7 -7
  51. package/dist/fixtures/proxyTag.d.ts +1 -1
  52. package/dist/fixtures/proxyTag.js +4 -4
  53. package/dist/index.d.ts +8 -8
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +4 -4
  56. package/dist/reporter/SelaReporter.d.ts +45 -12
  57. package/dist/reporter/SelaReporter.d.ts.map +1 -1
  58. package/dist/reporter/SelaReporter.js +139 -39
  59. package/dist/services/ASTSourceUpdater.d.ts +48 -3
  60. package/dist/services/ASTSourceUpdater.d.ts.map +1 -1
  61. package/dist/services/ASTSourceUpdater.js +283 -105
  62. package/dist/services/AnchorResolver.d.ts +157 -0
  63. package/dist/services/AnchorResolver.d.ts.map +1 -0
  64. package/dist/services/AnchorResolver.js +289 -0
  65. package/dist/services/ArgumentTypeAnalyzer.js +7 -7
  66. package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -1
  67. package/dist/services/BlastRadiusAnalyzer.js +5 -2
  68. package/dist/services/ChainValidator.js +22 -22
  69. package/dist/services/CrossFileHealer.js +7 -7
  70. package/dist/services/DecisionEngine.d.ts +51 -0
  71. package/dist/services/DecisionEngine.d.ts.map +1 -0
  72. package/dist/services/DecisionEngine.js +260 -0
  73. package/dist/services/DefinitionTracer.d.ts +1 -1
  74. package/dist/services/DefinitionTracer.d.ts.map +1 -1
  75. package/dist/services/DefinitionTracer.js +28 -13
  76. package/dist/services/DnaEditorService.d.ts +2 -2
  77. package/dist/services/DnaEditorService.d.ts.map +1 -1
  78. package/dist/services/DnaEditorService.js +81 -62
  79. package/dist/services/DnaIndexService.d.ts +1 -1
  80. package/dist/services/DnaIndexService.d.ts.map +1 -1
  81. package/dist/services/DnaIndexService.js +14 -14
  82. package/dist/services/HealReportService.d.ts +31 -55
  83. package/dist/services/HealReportService.d.ts.map +1 -1
  84. package/dist/services/HealReportService.js +864 -1240
  85. package/dist/services/HealingAdvisory.d.ts +9 -1
  86. package/dist/services/HealingAdvisory.d.ts.map +1 -1
  87. package/dist/services/HealingAdvisory.js +9 -1
  88. package/dist/services/HealingCacheService.d.ts +8 -8
  89. package/dist/services/HealingCacheService.d.ts.map +1 -1
  90. package/dist/services/HealingCacheService.js +24 -24
  91. package/dist/services/HealthReportService.d.ts +1 -1
  92. package/dist/services/HealthReportService.d.ts.map +1 -1
  93. package/dist/services/HealthReportService.js +25 -25
  94. package/dist/services/InitializerUpdater.d.ts.map +1 -1
  95. package/dist/services/InitializerUpdater.js +12 -2
  96. package/dist/services/IntentAuditor.d.ts.map +1 -1
  97. package/dist/services/IntentAuditor.js +32 -21
  98. package/dist/services/InteractiveReview.d.ts +8 -17
  99. package/dist/services/InteractiveReview.d.ts.map +1 -1
  100. package/dist/services/InteractiveReview.js +34 -124
  101. package/dist/services/LLMService.d.ts +1 -1
  102. package/dist/services/LLMService.js +16 -16
  103. package/dist/services/MutationApplier.d.ts +55 -0
  104. package/dist/services/MutationApplier.d.ts.map +1 -0
  105. package/dist/services/MutationApplier.js +322 -0
  106. package/dist/services/PRAutomationService.d.ts +2 -2
  107. package/dist/services/PRAutomationService.d.ts.map +1 -1
  108. package/dist/services/PRAutomationService.js +43 -39
  109. package/dist/services/PendingPromptLedger.d.ts +9 -2
  110. package/dist/services/PendingPromptLedger.d.ts.map +1 -1
  111. package/dist/services/PendingPromptLedger.js +31 -6
  112. package/dist/services/ReportGenerator.d.ts +116 -30
  113. package/dist/services/ReportGenerator.d.ts.map +1 -1
  114. package/dist/services/ReportGenerator.js +149 -62
  115. package/dist/services/ReportMergeService.d.ts +95 -0
  116. package/dist/services/ReportMergeService.d.ts.map +1 -0
  117. package/dist/services/ReportMergeService.js +0 -0
  118. package/dist/services/SafetyGuard.d.ts +4 -7
  119. package/dist/services/SafetyGuard.d.ts.map +1 -1
  120. package/dist/services/SafetyGuard.js +29 -106
  121. package/dist/services/SelectorSanitizer.d.ts +52 -0
  122. package/dist/services/SelectorSanitizer.d.ts.map +1 -0
  123. package/dist/services/SelectorSanitizer.js +318 -0
  124. package/dist/services/SnapshotService.js +6 -6
  125. package/dist/services/SourceLinkService.d.ts +2 -2
  126. package/dist/services/SourceLinkService.d.ts.map +1 -1
  127. package/dist/services/SourceLinkService.js +31 -22
  128. package/dist/services/SourceUpdater.d.ts +1 -1
  129. package/dist/services/SourceUpdater.d.ts.map +1 -1
  130. package/dist/services/SourceUpdater.js +44 -26
  131. package/dist/services/TemplateDiffService.d.ts.map +1 -1
  132. package/dist/services/TemplateDiffService.js +18 -15
  133. package/dist/services/TraceBackEngine.d.ts +67 -0
  134. package/dist/services/TraceBackEngine.d.ts.map +1 -0
  135. package/dist/services/TraceBackEngine.js +672 -0
  136. package/dist/services/WorkspaceSnapshotService.d.ts +6 -6
  137. package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -1
  138. package/dist/services/WorkspaceSnapshotService.js +10 -12
  139. package/dist/types/index.d.ts +1 -1
  140. package/dist/utils/DOMUtils.d.ts +18 -2
  141. package/dist/utils/DOMUtils.d.ts.map +1 -1
  142. package/dist/utils/DOMUtils.js +335 -49
  143. package/dist/utils/IsolatedDiff.d.ts +2 -2
  144. package/dist/utils/IsolatedDiff.d.ts.map +1 -1
  145. package/dist/utils/IsolatedDiff.js +13 -10
  146. package/package.json +2 -2
@@ -6,9 +6,18 @@ exports.resolveThresholds = resolveThresholds;
6
6
  exports.parseEnvBoolean = parseEnvBoolean;
7
7
  exports.resolveConfig = resolveConfig;
8
8
  const PRESET_MAP = {
9
- conservative: { minHealerConfidence: 92, auditorStrictness: 'strict', assertionSimilarityFloor: 0.85 },
10
- balanced: { minHealerConfidence: 85, auditorStrictness: 'balanced', assertionSimilarityFloor: 0.70 },
11
- aggressive: { minHealerConfidence: 75, auditorStrictness: 'loose', assertionSimilarityFloor: 0.55 },
9
+ conservative: {
10
+ minHealerConfidence: 92,
11
+ auditorStrictness: "strict",
12
+ },
13
+ balanced: {
14
+ minHealerConfidence: 85,
15
+ auditorStrictness: "balanced",
16
+ },
17
+ aggressive: {
18
+ minHealerConfidence: 75,
19
+ auditorStrictness: "loose",
20
+ },
12
21
  };
13
22
  const STRICTNESS_CONFIDENCE = {
14
23
  strict: 90,
@@ -26,15 +35,13 @@ function resolveThresholds(config) {
26
35
  // Explicit thresholds always win over preset expansion
27
36
  const merged = { ...fromPreset, ...config.thresholds };
28
37
  const minHealerConfidence = merged.minHealerConfidence ?? 85;
29
- const auditorStrictness = merged.auditorStrictness ?? 'balanced';
30
- const assertionSimilarityFloor = merged.assertionSimilarityFloor ?? 0.7;
38
+ const auditorStrictness = merged.auditorStrictness ?? "balanced";
31
39
  return {
32
40
  confidenceHardStop: minHealerConfidence,
33
41
  confidenceReviewThreshold: 95,
34
- assertionSimilarityFloor,
35
42
  auditorConfidenceMin: STRICTNESS_CONFIDENCE[auditorStrictness],
36
- // allowSuspicious is derived never independently settable to avoid footguns
37
- allowSuspicious: auditorStrictness === 'loose',
43
+ // allowSuspicious is derived - never independently settable to avoid footguns
44
+ allowSuspicious: auditorStrictness === "loose",
38
45
  auditorStrictness,
39
46
  };
40
47
  }
@@ -42,37 +49,36 @@ function resolvePRAutomation(config) {
42
49
  const pr = config.prAutomation ?? {};
43
50
  // Legacy bridge: autoCommit:true with no explicit prAutomation block
44
51
  // → enable prAutomation in directCommit mode. Explicit prAutomation always wins.
45
- const legacyEnabled = config.autoCommit === true &&
46
- config.prAutomation === undefined;
52
+ const legacyEnabled = config.autoCommit === true && config.prAutomation === undefined;
47
53
  const enabled = pr.enabled ?? legacyEnabled;
48
- const strategy = pr.strategy ?? (legacyEnabled ? 'directCommit' : 'readOnly');
54
+ const strategy = pr.strategy ?? (legacyEnabled ? "directCommit" : "readOnly");
49
55
  return {
50
56
  enabled,
51
57
  strategy,
52
- protectedBranches: pr.protectedBranches ?? ['main', 'master', 'release'],
58
+ protectedBranches: pr.protectedBranches ?? ["main", "master", "release"],
53
59
  reviewThresholds: {
54
60
  minConfidenceForDirectCommit: pr.reviewThresholds?.minConfidenceForDirectCommit ?? 0,
55
61
  minAuditorScoreForDirectCommit: pr.reviewThresholds?.minAuditorScoreForDirectCommit ?? 0,
56
- downgradeTo: pr.reviewThresholds?.downgradeTo ?? 'draftPR',
62
+ downgradeTo: pr.reviewThresholds?.downgradeTo ?? "draftPR",
57
63
  },
58
- onBugDetected: pr.onBugDetected ?? 'failCI',
59
- branchNameTemplate: pr.branchNameTemplate ?? 'sela/heal-${id}',
60
- titleTemplate: pr.titleTemplate ?? 'fix(sela): heal selector in ${fileName}',
64
+ onBugDetected: pr.onBugDetected ?? "failCI",
65
+ branchNameTemplate: pr.branchNameTemplate ?? "sela/heal-${id}",
66
+ titleTemplate: pr.titleTemplate ?? "fix(sela): heal selector in ${fileName}",
61
67
  bodyTemplate: pr.bodyTemplate ?? null,
62
68
  labels: pr.labels ?? [],
63
- reportArtifactPath: pr.reportArtifactPath ?? 'sela-report.html',
69
+ reportArtifactPath: pr.reportArtifactPath ?? "sela-report.html",
64
70
  };
65
71
  }
66
72
  // ═══════════════════════════════════════════════════════════════════
67
- // ENV FLAG PARSING strict, fail-fast
73
+ // ENV FLAG PARSING - strict, fail-fast
68
74
  //
69
75
  // Accepted truthy values (case-insensitive): "1", "true", "yes", "on".
70
76
  // Accepted falsy values (case-insensitive): "0", "false", "no", "off", "".
71
77
  // Anything else → throws so misconfigured CI environments fail loudly
72
78
  // instead of silently running the wrong mode.
73
79
  // ═══════════════════════════════════════════════════════════════════
74
- const ENV_TRUTHY = new Set(['1', 'true', 'yes', 'on']);
75
- const ENV_FALSY = new Set(['0', 'false', 'no', 'off', '']);
80
+ const ENV_TRUTHY = new Set(["1", "true", "yes", "on"]);
81
+ const ENV_FALSY = new Set(["0", "false", "no", "off", ""]);
76
82
  function parseEnvBoolean(varName, rawValue) {
77
83
  if (rawValue === undefined)
78
84
  return false;
@@ -89,18 +95,18 @@ function resolveConfig(config, env = process.env) {
89
95
  // When prAutomation owns the git pipeline, suppress per-heal git side-effects
90
96
  // in SourceUpdater (autoCommit + updateStrategy:'branch') to avoid double-commits.
91
97
  const suppressLegacyGit = prAutomation.enabled;
92
- const requestedUpdateStrategy = config.updateStrategy ?? 'inPlace';
93
- const updateStrategy = suppressLegacyGit && requestedUpdateStrategy === 'branch'
94
- ? 'inPlace'
98
+ const requestedUpdateStrategy = config.updateStrategy ?? "inPlace";
99
+ const updateStrategy = suppressLegacyGit && requestedUpdateStrategy === "branch"
100
+ ? "inPlace"
95
101
  : requestedUpdateStrategy;
96
102
  const autoCommit = suppressLegacyGit ? false : (config.autoCommit ?? false);
97
- const dryRun = parseEnvBoolean('SELA_DRY_RUN', env.SELA_DRY_RUN);
98
- const noCache = parseEnvBoolean('SELA_NO_CACHE', env.SELA_NO_CACHE);
103
+ const dryRun = parseEnvBoolean("SELA_DRY_RUN", env.SELA_DRY_RUN);
104
+ const noCache = parseEnvBoolean("SELA_NO_CACHE", env.SELA_NO_CACHE);
99
105
  return {
100
106
  thresholds: resolveThresholds(config),
101
107
  updateStrategy,
102
108
  autoCommit,
103
- dnaStoragePath: config.dnaStoragePath ?? 'fixwright-snapshots',
109
+ dnaStoragePath: config.dnaStoragePath ?? "sela-snapshots",
104
110
  prAutomation,
105
111
  agenticDiscovery: {
106
112
  enabled: config.agenticDiscovery?.enabled ?? false,
@@ -29,7 +29,7 @@ export declare class HealingRegistry {
29
29
  /**
30
30
  * Resolve a selector within a specific call-site context.
31
31
  * Falls back to a context-free lookup ONLY when the fingerprint
32
- * has no entry prevents poisoning while still enabling same-file reuse.
32
+ * has no entry - prevents poisoning while still enabling same-file reuse.
33
33
  */
34
34
  resolveSelector(selector: string, ctx?: SelectorContext): string;
35
35
  private walkChain;
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // src/engine/HealingRegistry.ts full replacement
2
+ // src/engine/HealingRegistry.ts - full replacement
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.HealingRegistry = void 0;
5
5
  const crypto_1 = require("crypto");
@@ -60,7 +60,7 @@ class HealingRegistry {
60
60
  /**
61
61
  * Resolve a selector within a specific call-site context.
62
62
  * Falls back to a context-free lookup ONLY when the fingerprint
63
- * has no entry prevents poisoning while still enabling same-file reuse.
63
+ * has no entry - prevents poisoning while still enabling same-file reuse.
64
64
  */
65
65
  resolveSelector(selector, ctx) {
66
66
  if (ctx) {
@@ -72,7 +72,7 @@ class HealingRegistry {
72
72
  return resolved;
73
73
  }
74
74
  }
75
- return selector; // No global fallback intentional
75
+ return selector; // No global fallback - intentional
76
76
  }
77
77
  walkChain(selector, store) {
78
78
  let current = selector;
@@ -36,7 +36,7 @@ export declare class SelaEngine {
36
36
  * `gitUnifiedDiff` payload yet.
37
37
  *
38
38
  * Carefully skips the diff preamble (--- a/file, +++ b/file, "diff ",
39
- * "index ", rename headers) those lines would otherwise be mistaken for
39
+ * "index ", rename headers) - those lines would otherwise be mistaken for
40
40
  * a -/+ change pair and produce nonsense like the original "line replaced
41
41
  * by itself" output. Real change lines only count once the parser has seen
42
42
  * a "@@" hunk header.
@@ -1 +1 @@
1
- {"version":3,"file":"SelaEngine.d.ts","sourceRoot":"","sources":["../../src/engine/SelaEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAQxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,EAAe,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AA+DhE,qBAAa,UAAU;IACrB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,mBAAmB,CAAmB;IAC9C,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,eAAe,CAAkC;;IAqBnD,YAAY,CAChB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiDnB,IAAI,CACR,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAmB,GAC5B,OAAO,CAAC,MAAM,CAAC;IAykBlB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,aAAa;IAarB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,2BAA2B;IA4BnC,OAAO,CAAC,yBAAyB;IAwBjC,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,oBAAoB;IAuC5B,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrD,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;YAgItB,aAAa;IAsB3B,OAAO,CAAC,0BAA0B;IAiClC,OAAO,CAAC,WAAW;IA6Bb,wBAAwB,CAC5B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CAqBnB;AAED,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"SelaEngine.d.ts","sourceRoot":"","sources":["../../src/engine/SelaEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAaxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,EAAe,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAmEhE,qBAAa,UAAU;IACrB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,mBAAmB,CAAmB;IAC9C,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,eAAe,CAAkC;;IAqBnD,YAAY,CAChB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiDnB,IAAI,CACR,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAmB,GAC5B,OAAO,CAAC,MAAM,CAAC;IA+oBlB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;IAerB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,2BAA2B;IA4BnC,OAAO,CAAC,yBAAyB;IAmCjC,OAAO,CAAC,kBAAkB;IA8D1B,OAAO,CAAC,oBAAoB;IAyD5B,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrD,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;YAqItB,aAAa;IAsB3B,OAAO,CAAC,0BAA0B;IAiClC,OAAO,CAAC,WAAW;IA6Bb,wBAAwB,CAC5B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CAqBnB;AAED,OAAO,EAAE,CAAC"}
@@ -91,13 +91,13 @@ class SelaEngine {
91
91
  // pre-scan. Keeping it separate from the SourceUpdater's project avoids
92
92
  // polluting that cache with files we may never actually mutate.
93
93
  this.astDirectiveScanner = new ASTSourceUpdater_1.ASTSourceUpdater();
94
- // Local healing cache short-circuits the LLM call when an identical
94
+ // Local healing cache - short-circuits the LLM call when an identical
95
95
  // (filePath, oldSelector) pair was healed safely in a prior session.
96
96
  // Disabled when SELA_NO_CACHE=1; reads/writes skipped during dry runs.
97
97
  this.healingCache = HealingCacheService_1.sharedHealingCache;
98
98
  }
99
99
  // ─────────────────────────────────────────────────────────────
100
- // healArgument repairs a wrong action argument (e.g. selectOption)
100
+ // healArgument - repairs a wrong action argument (e.g. selectOption)
101
101
  // ─────────────────────────────────────────────────────────────
102
102
  async healArgument(page, selector, action, oldArgument, stableId, filePath, line) {
103
103
  console.log(`[Sela] 🔧 HEALING ARGUMENT for action '${action}': "${oldArgument}"`);
@@ -130,7 +130,7 @@ CRITICAL: Do NOT return a CSS selector like "#my-select". Return plain text only
130
130
  return null;
131
131
  }
132
132
  // ─────────────────────────────────────────────────────────────
133
- // heal repairs a broken selector
133
+ // heal - repairs a broken selector
134
134
  // ─────────────────────────────────────────────────────────────
135
135
  async heal(page, fullSelector, elementSelectorOnly, stableId, filePath, line, healMode = "action") {
136
136
  console.log(`\n[Sela] 🛠️ HEALING START for: ${stableId}`);
@@ -148,7 +148,7 @@ CRITICAL: Do NOT return a CSS selector like "#my-select". Return plain text only
148
148
  catch (directiveErr) {
149
149
  if ((0, SelaError_1.isSelaErrorFrom)(directiveErr, "ASTUpdater") &&
150
150
  directiveErr.code === SelaError_1.AST_UPDATER_CODES.HEAL_DISABLED_BY_DIRECTIVE) {
151
- console.warn(`[Sela] 🛑 Skipped by Developer ${directiveErr.reason}`);
151
+ console.warn(`[Sela] 🛑 Skipped by Developer - ${directiveErr.reason}`);
152
152
  const skipEvent = {
153
153
  kind: "FAILED",
154
154
  stableId,
@@ -218,10 +218,10 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
218
218
  return "";
219
219
  const lines = [];
220
220
  if (anchors.closestLabel) {
221
- lines.push(`- Label: "${anchors.closestLabel}" the UI label or heading associated with this element.`);
221
+ lines.push(`- Label: "${anchors.closestLabel}" - the UI label or heading associated with this element.`);
222
222
  }
223
223
  if (anchors.rowAnchor) {
224
- lines.push(`- Row key: "${anchors.rowAnchor}" unique cell text identifying the table row this element belonged to.`);
224
+ lines.push(`- Row key: "${anchors.rowAnchor}" - unique cell text identifying the table row this element belonged to.`);
225
225
  }
226
226
  if (lines.length === 0)
227
227
  return "";
@@ -236,12 +236,12 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
236
236
  // pair AND SafetyGuard cleared it, replay the cached fix instead
237
237
  // of paying the LLM round-trip. Disabled when SELA_NO_CACHE=1.
238
238
  // The synthetic aiFix is fed through SafetyGuard exactly like a
239
- // fresh LLM response cache is a latency optimisation, never a
239
+ // fresh LLM response - cache is a latency optimisation, never a
240
240
  // safety bypass.
241
241
  let aiFix = null;
242
242
  let cacheHit = false;
243
243
  // Fingerprint inputs the cache key depends on. Recomputed every
244
- // heal so a DNA rewrite which changes `dnaContentHash`
244
+ // heal so a DNA rewrite - which changes `dnaContentHash` -
245
245
  // automatically invalidates every prior entry without an explicit
246
246
  // purge.
247
247
  const dnaContentHash = (0, HealingCacheService_1.hashDnaContent)(lastKnownState ?? null);
@@ -255,13 +255,14 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
255
255
  if (!this.config.noCache) {
256
256
  const cached = this.healingCache.get(cacheKeyInput);
257
257
  if (cached) {
258
- console.log(`[Sela] 🧊 Cache hit (0ms LLM) replaying healed selector "${cached.healedSelector}"`);
258
+ console.log(`[Sela] 🧊 Cache hit (0ms LLM) - replaying healed selector "${cached.healedSelector}"`);
259
259
  aiFix = {
260
260
  status: "FIXED",
261
261
  new_selector: cached.healedSelector,
262
262
  chainSegments: cached.chainSegments,
263
- segments: cached.segments ??
264
- [{ type: "element", selector: cached.healedSelector }],
263
+ segments: cached.segments ?? [
264
+ { type: "element", selector: cached.healedSelector },
265
+ ],
265
266
  confidence: cached.confidence,
266
267
  contentChange: cached.contentChange,
267
268
  explanation: cached.explanation ?? "Replayed from local healing cache",
@@ -308,7 +309,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
308
309
  console.log(`[Sela] 🔍 Step 3.5: Live text fetch skipped (element not yet rendered or non-text)`);
309
310
  }
310
311
  // ── Step 3.6: Atomic v2 capture of the candidate element ──
311
- // Single page.evaluate() call collects visibility, ancestry,
312
+ // Single page.evaluate() call - collects visibility, ancestry,
312
313
  // and anchors of the healed element for SafetyGuard use.
313
314
  // Returns null on any failure; never blocks the heal.
314
315
  const liveSnapshot = await this.snapshotService.captureElement(page, elementOnlySelector, successfulPath);
@@ -321,7 +322,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
321
322
  : "";
322
323
  const occFlag = liveVisibility?.isOccluded ? " 🫥 OCCLUDED" : "";
323
324
  console.log(`[Sela] 🔍 Step 3.6: Live v2 capture complete` +
324
- `${ghostFlag}${occFlag} ancestry depth: ${liveAncestry?.length ?? 0}`);
325
+ `${ghostFlag}${occFlag} - ancestry depth: ${liveAncestry?.length ?? 0}`);
325
326
  }
326
327
  else {
327
328
  console.log(`[Sela] 🔍 Step 3.6: Live v2 capture skipped`);
@@ -355,7 +356,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
355
356
  }
356
357
  // ── Report: PROTECTED (or BLOCKED non-INCONSISTENT) ─────────
357
358
  // The auto-fix was blocked. If the auditor verdict is INCONSISTENT
358
- // this is a "Security Win" a masked regression was caught.
359
+ // this is a "Security Win" - a masked regression was caught.
359
360
  const protectedEvent = {
360
361
  kind: "PROTECTED",
361
362
  stableId,
@@ -407,17 +408,69 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
407
408
  parts.push(`${breakdown.penalty} ancestry drift`);
408
409
  if (breakdown.bonus !== 0)
409
410
  parts.push(`+${breakdown.bonus} anchor match`);
410
- console.log(`[Sela] 📊 Score AI: ${fmtPctEngine(aiFix.confidence)} | ` +
411
+ console.log(`[Sela] 📊 Score - AI: ${fmtPctEngine(aiFix.confidence)} | ` +
411
412
  `Auditor: ${fmtPctEngine(breakdown.adjustedConfidence)} ` +
412
413
  `(raw ${fmtPctEngine(breakdown.rawConfidence)}, ${parts.join(", ")})`);
413
414
  }
414
415
  console.log(`[Sela] 🚀 Rebuilt Full Runtime Selector (Clean): ${newFullSelector}`);
415
- const updateResult = SourceUpdater_1.SourceUpdater.update({ filePath, line }, elementSelectorOnly, newFullSelector, neighborhoodDom, undefined, fullSelector, aiFix.segments, aiFix.contentChange, aiFix.chainSegments, aiFix.originalChainHint, this.config.updateStrategy, this.config.autoCommit);
416
+ // ── PRIMARY: composeHeal trace-back pipeline (Stages 1-4) ──────────
417
+ // Trace the failing call-site to its source declaration and apply a
418
+ // write-disciplined Method-Shift / in-place mutation through the
419
+ // type-safety gate. Restricted to plain in-place writes (commentOnly /
420
+ // branch / autoCommit / dry-run keep the legacy git-aware path).
421
+ // Falls back to the legacy regex/semantic engine on ABORT / PROMPT.
422
+ let updateResult;
423
+ const plainInPlace = (!this.config.updateStrategy ||
424
+ this.config.updateStrategy === "inPlace") &&
425
+ !this.config.autoCommit;
426
+ const resolvedForCompose = SourceUpdater_1.SourceUpdater.resolveFilePath(filePath);
427
+ if (plainInPlace && !DryRunGuard_1.DryRunGuard.active() && resolvedForCompose) {
428
+ try {
429
+ WorkspaceSnapshotService_1.sharedWorkspaceSnapshot.preWrite(resolvedForCompose);
430
+ const composed = ASTSourceUpdater_1.ASTSourceUpdater.composeHeal({
431
+ filePath: resolvedForCompose,
432
+ line,
433
+ newSelector: newFullSelector,
434
+ apply: true,
435
+ applyOptions: { respectDryRun: true },
436
+ });
437
+ const strat = composed.decision?.strategy;
438
+ if (composed.kind === "decision" &&
439
+ composed.outcome?.status === "applied" &&
440
+ (strat === "MUTATE_IN_PLACE" || strat === "FORK_AT_TEST")) {
441
+ WorkspaceSnapshotService_1.sharedWorkspaceSnapshot.postWrite(resolvedForCompose);
442
+ const wl = composed.writtenLine ?? line;
443
+ updateResult = {
444
+ success: true,
445
+ reason: `composeHeal[${strat}]: ${composed.decision.reason}`,
446
+ lineUpdated: wl - 1,
447
+ healedLocatorString: newFullSelector,
448
+ definitionSite: { file: resolvedForCompose, line: wl - 1 },
449
+ blastRadius: composed.decision.blastRadius,
450
+ };
451
+ console.log(`[Sela] 🧠 composeHeal primary path applied (${strat})`);
452
+ }
453
+ else {
454
+ const why = composed.kind === "abort"
455
+ ? `abort:${composed.trace.code ?? composed.trace.status}`
456
+ : `${strat ?? "no-decision"}/${composed.outcome?.status ?? "not-applied"}`;
457
+ console.log(`[Sela] ↩️ composeHeal declined (${why}) - falling back to legacy heal`);
458
+ }
459
+ }
460
+ catch (e) {
461
+ console.warn(`[Sela] composeHeal primary failed (${e?.message}) - falling back to legacy heal`);
462
+ }
463
+ }
464
+ // ── FALLBACK: legacy regex/semantic heal (also handles dry-run /
465
+ // commentOnly / branch / autoCommit / cross-file). ──────────────
466
+ if (!updateResult) {
467
+ updateResult = SourceUpdater_1.SourceUpdater.update({ filePath, line }, elementSelectorOnly, newFullSelector, neighborhoodDom, undefined, fullSelector, aiFix.segments, aiFix.contentChange, aiFix.chainSegments, aiFix.originalChainHint, this.config.updateStrategy, this.config.autoCommit);
468
+ }
416
469
  // Resolve the line that was actually mutated. Order of precedence:
417
470
  // 1. updateResult.lineUpdated (the strategy's literal write location)
418
471
  // 2. updateResult.definitionSite.line (semantic JumpToDef target,
419
472
  // used when the mutation crossed into a const/variable declaration)
420
- // 3. line (the original failure line last-resort fallback)
473
+ // 3. line (the original failure line - last-resort fallback)
421
474
  // For cross-file definitionSite.file, we still read the new line from
422
475
  // the SAME file that was mutated.
423
476
  const defSite = updateResult.definitionSite;
@@ -430,7 +483,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
430
483
  line;
431
484
  const mutatedFilePath = !sameFileDef && defSite ? defSite.file : filePath;
432
485
  // Clean-Room isolated diff. We diff the in-memory snapshot recorded
433
- // by WorkspaceSnapshotService (contentBefore disk state right
486
+ // by WorkspaceSnapshotService (contentBefore - disk state right
434
487
  // before Sela's first write to this file) against the post-write
435
488
  // disk state. The result contains EXCLUSIVELY Sela's selector swap;
436
489
  // any developer dirty edits sit identically in both buffers and
@@ -441,12 +494,14 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
441
494
  // Backward-compat: keep oldCodeLine/newCodeLine populated from the
442
495
  // first -/+ pair inside the diff. When git produced no diff (file
443
496
  // untracked, git unavailable, …) fall back to a direct disk read of
444
- // the mutated line strictly inferior but preserves old reports.
445
- const oldCodeLine = firstChange.oldLine ?? this._safeReadLine(mutatedFilePath, writtenLine);
446
- const newCodeLine = firstChange.newLine ?? this._safeReadLine(mutatedFilePath, writtenLine);
497
+ // the mutated line - strictly inferior but preserves old reports.
498
+ const oldCodeLine = firstChange.oldLine ??
499
+ this._safeReadLine(mutatedFilePath, writtenLine);
500
+ const newCodeLine = firstChange.newLine ??
501
+ this._safeReadLine(mutatedFilePath, writtenLine);
447
502
  const canonicalSelector = updateResult.healedLocatorString ?? newFullSelector;
448
503
  console.log(`[Sela] ✅ Canonical selector (disk == runtime): "${canonicalSelector}"`);
449
- // Buffer CLI-ready metadata merged into DNA at commitUpdates() time.
504
+ // Buffer CLI-ready metadata - merged into DNA at commitUpdates() time.
450
505
  // Sanitize filePath: strip any residual "at " stack-trace prefix + whitespace,
451
506
  // then resolve to an absolute path before converting to project-relative form.
452
507
  const match = filePath.match(/at\s+(.*)/i);
@@ -515,7 +570,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
515
570
  contentChange: aiFix.contentChange,
516
571
  };
517
572
  HealReportService_1.sharedHealReport.record(healedEvent);
518
- // ── Cache write persist this safe heal for future sessions ──
573
+ // ── Cache write - persist this safe heal for future sessions ──
519
574
  // Best-effort: failures are logged inside the service and never
520
575
  // block the heal return. Skipped automatically during dry runs
521
576
  // and when SELA_NO_CACHE=1.
@@ -536,7 +591,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
536
591
  }
537
592
  return canonicalSelector;
538
593
  }
539
- // AI did not return FIXED record as FAILED.
594
+ // AI did not return FIXED - record as FAILED.
540
595
  const failedEvent = {
541
596
  kind: "FAILED",
542
597
  stableId,
@@ -562,9 +617,12 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
562
617
  // Prefer the structured instanceof check; fall back to message-substring
563
618
  // detection for any legacy throw sites that have not yet been migrated.
564
619
  const isSafetyBlock = (0, SelaError_1.isSelaErrorFrom)(error, "SafetyGuard") ||
565
- (typeof error?.message === "string" && error.message.includes("[Sela-SafetyGuard]")) ||
566
- (typeof error?.message === "string" && error.message.includes("[SafetyGuard]"));
567
- const isNotFoundAlreadyRecorded = typeof error?.message === "string" && error.message === "AI could not provide a fix";
620
+ (typeof error?.message === "string" &&
621
+ error.message.includes("[Sela-SafetyGuard]")) ||
622
+ (typeof error?.message === "string" &&
623
+ error.message.includes("[SafetyGuard]"));
624
+ const isNotFoundAlreadyRecorded = typeof error?.message === "string" &&
625
+ error.message === "AI could not provide a fix";
568
626
  if (!isSafetyBlock && !isNotFoundAlreadyRecorded) {
569
627
  const failedEvent = {
570
628
  kind: "FAILED",
@@ -594,14 +652,20 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
594
652
  if (!filePath)
595
653
  return "";
596
654
  const match = filePath.match(/at\s+(.*)/i);
597
- const cleaned = (match ? match[1] : filePath).replace(/^\(|\)$/g, "").trim();
598
- const abs = path.isAbsolute(cleaned) ? cleaned : path.resolve(process.cwd(), cleaned);
655
+ const cleaned = (match ? match[1] : filePath)
656
+ .replace(/^\(|\)$/g, "")
657
+ .trim();
658
+ const abs = path.isAbsolute(cleaned)
659
+ ? cleaned
660
+ : path.resolve(process.cwd(), cleaned);
599
661
  return path.relative(process.cwd(), abs) || abs;
600
662
  }
601
663
  _safeReadLine(filePath, lineNumber) {
602
664
  try {
603
665
  const cleaned = this._toReportFile(filePath);
604
- const abs = path.isAbsolute(cleaned) ? cleaned : path.resolve(process.cwd(), cleaned);
666
+ const abs = path.isAbsolute(cleaned)
667
+ ? cleaned
668
+ : path.resolve(process.cwd(), cleaned);
605
669
  if (!fs.existsSync(abs))
606
670
  return "";
607
671
  const lines = fs.readFileSync(abs, "utf8").split(/\r?\n/);
@@ -654,7 +718,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
654
718
  * `gitUnifiedDiff` payload yet.
655
719
  *
656
720
  * Carefully skips the diff preamble (--- a/file, +++ b/file, "diff ",
657
- * "index ", rename headers) those lines would otherwise be mistaken for
721
+ * "index ", rename headers) - those lines would otherwise be mistaken for
658
722
  * a -/+ change pair and produce nonsense like the original "line replaced
659
723
  * by itself" output. Real change lines only count once the parser has seen
660
724
  * a "@@" hunk header.
@@ -694,7 +758,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
694
758
  if (!meta || !meta.auditorVerdict)
695
759
  return null;
696
760
  // Keep auditor confidence as `undefined` when SafetyGuard did not produce
697
- // one the renderer fmtPct helper turns it into "n/a" rather than 0%.
761
+ // one - the renderer fmtPct helper turns it into "n/a" rather than 0%.
698
762
  const conf = typeof meta.auditorConfidence === "number" &&
699
763
  Number.isFinite(meta.auditorConfidence)
700
764
  ? meta.auditorConfidence
@@ -766,15 +830,16 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
766
830
  _buildReasoningSteps(ctx) {
767
831
  const steps = [];
768
832
  if (ctx.dnaTag || ctx.dnaText) {
769
- steps.push(`Recovered DNA baseline previously a <${ctx.dnaTag ?? "?"}>` +
770
- (ctx.dnaText ? ` with text "${ctx.dnaText}"` : "") + ".");
833
+ steps.push(`Recovered DNA baseline - previously a <${ctx.dnaTag ?? "?"}>` +
834
+ (ctx.dnaText ? ` with text "${ctx.dnaText}"` : "") +
835
+ ".");
771
836
  }
772
837
  if (ctx.successfulPath.length > 0) {
773
838
  steps.push(`Resolved DOM context inside ${ctx.successfulPath.length} nested frame(s): ${ctx.successfulPath.join(" >> ")}.`);
774
839
  }
775
840
  const firstSeg = ctx.aiFix.chainSegments?.[0];
776
841
  if (firstSeg) {
777
- steps.push(`AI preserved the ${firstSeg.type} pattern semantic locator over raw CSS path.`);
842
+ steps.push(`AI preserved the ${firstSeg.type} pattern - semantic locator over raw CSS path.`);
778
843
  }
779
844
  if (ctx.aiFix.explanation) {
780
845
  steps.push(`AI reasoning: ${ctx.aiFix.explanation}`);
@@ -783,7 +848,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
783
848
  if (ctx.aiFix.contentChange) {
784
849
  steps.push(`Detected content drift: "${ctx.aiFix.contentChange.oldText}" → "${ctx.aiFix.contentChange.newText}".`);
785
850
  }
786
- steps.push(`SafetyGuard verdict: ${ctx.safetyLevel} change cleared for write.`);
851
+ steps.push(`SafetyGuard verdict: ${ctx.safetyLevel} - change cleared for write.`);
787
852
  steps.push(`Source updated via ${ctx.strategy} at line ${ctx.writtenLine}.`);
788
853
  if (ctx.blastRadius != null && ctx.blastRadius > 0) {
789
854
  steps.push(`Blast radius: ${ctx.blastRadius} dependent test reference(s) inherited the fix.`);
@@ -808,7 +873,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
808
873
  this.testTitleBuffer.clear();
809
874
  SourceUpdater_1.SourceUpdater.flushAdvisories();
810
875
  }
811
- // ── Sela Insights render the transparent healing report ───────
876
+ // ── Sela Insights - render the transparent healing report ───────
812
877
  let reportHtmlPath = null;
813
878
  const healedEvents = HealReportService_1.sharedHealReport.getHealedEvents();
814
879
  const protectedEvents = HealReportService_1.sharedHealReport.getProtectedEvents();
@@ -827,11 +892,12 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
827
892
  // ── Dual-Mode post-run lifecycle ─────────────────────────────────
828
893
  //
829
894
  // CI (process.env.CI truthy) → Clean-Room PR automation (existing flow).
830
- // Local DX (CI falsy) → Interactive CLI review of each mutated
831
- // file; Apply keeps the on-disk fix, Reject
832
- // rewinds via WorkspaceSnapshotService.
895
+ // Local DX (CI falsy) → Write-and-notify: AST mutations are
896
+ // already on disk; the reporter prints a
897
+ // diff + vscode:// deeplink + report link
898
+ // via printHealReview() (no Y/N prompt).
833
899
  //
834
- // The interactive branch deliberately bypasses PR automation because:
900
+ // The local branch deliberately bypasses PR automation because:
835
901
  // • AST fixes are ALREADY persisted to disk (the test passed on them).
836
902
  // • Local devs want to inspect + cherry-pick, not auto-commit.
837
903
  if (isCiEnvironment()) {
@@ -858,11 +924,11 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
858
924
  }
859
925
  }
860
926
  else if (healedEvents.length > 0) {
861
- // Local DX: do NOT block this process on stdin — workers have no
862
- // TTY and would deadlock until Playwright's per-test timeout fires.
863
- // Serialise the mutated snapshots to a cross-process ledger; the
864
- // SelaReporter drains it from `onEnd()` in the main process where
865
- // an interactive `readline` is safe.
927
+ // Local DX: serialise the mutated snapshots to a cross-process
928
+ // ledger. The SelaReporter drains it from `onEnd()` in the main
929
+ // process and prints a non-blocking summary (diff + vscode://
930
+ // deeplink). Mutations are already on disk - the ledger only
931
+ // exists so the reporter knows what to narrate.
866
932
  try {
867
933
  (0, PendingPromptLedger_1.writePendingPromptsLedger)({
868
934
  cwd: process.cwd(),
@@ -887,12 +953,12 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
887
953
  WorkspaceSnapshotService_1.sharedWorkspaceSnapshot.clear();
888
954
  }
889
955
  // ─────────────────────────────────────────────────────────────
890
- // fetchLiveText frame-aware innerText fetch (zero-trust probe)
956
+ // fetchLiveText - frame-aware innerText fetch (zero-trust probe)
891
957
  //
892
958
  // Navigates the frame chain encoded in successfulPath, then calls
893
959
  // .first().innerText() on the element-only selector. Uses a short
894
960
  // 1.5 s timeout so it never adds meaningful latency. Returns null
895
- // on ANY failure the caller must treat null as "no data" and skip
961
+ // on ANY failure - the caller must treat null as "no data" and skip
896
962
  // live verification rather than blocking the heal.
897
963
  // ─────────────────────────────────────────────────────────────
898
964
  async fetchLiveText(page, elementOnlySelector, framePath) {
@@ -923,7 +989,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
923
989
  p === "frame" ||
924
990
  p.includes("frame-"));
925
991
  if (aiHasFrameSegments) {
926
- console.log(`[Sela] 🔗 AI returned full frame path using directly: ${aiNewSelector}`);
992
+ console.log(`[Sela] 🔗 AI returned full frame path - using directly: ${aiNewSelector}`);
927
993
  return aiNewSelector;
928
994
  }
929
995
  return [...frameParts, ...aiParts].join(" >> ");
@@ -933,7 +999,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
933
999
  const ignoreList = [
934
1000
  "node_modules",
935
1001
  ".git",
936
- "fixwright-snapshots",
1002
+ "sela-snapshots",
937
1003
  "dist",
938
1004
  "test-results",
939
1005
  "tests/reset-demo.ts",
@@ -951,7 +1017,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
951
1017
  return arrayOfFiles;
952
1018
  }
953
1019
  // ─────────────────────────────────────────────────────────────
954
- // captureSuccessfulElement capture and buffer a v2 DNA snapshot.
1020
+ // captureSuccessfulElement - capture and buffer a v2 DNA snapshot.
955
1021
  //
956
1022
  // Replaces the previous DOMUtils.getElementDNA() path with a single
957
1023
  // captureElement() call that collects all v2 metrics atomically.
@@ -63,7 +63,6 @@ export declare const SAFETY_GUARD_CODES: {
63
63
  readonly BLOCKED_ROLE_SWAP_ASSERTION: "SG_BLOCKED_ROLE_SWAP_ASSERTION";
64
64
  readonly FAIL_HARD_AUDITOR_INCONSISTENT: "SG_FAIL_HARD_AUDITOR_INCONSISTENT";
65
65
  readonly BLOCKED_AUDITOR_SUSPICIOUS: "SG_BLOCKED_AUDITOR_SUSPICIOUS";
66
- readonly BLOCKED_SIMILARITY_FLOOR: "SG_BLOCKED_SIMILARITY_FLOOR";
67
66
  /** Generic dispatcher when SafetyDecision arrives without an explicit code. */
68
67
  readonly GENERIC_REJECTION: "SG_GENERIC_REJECTION";
69
68
  };
@@ -120,6 +119,14 @@ export declare const REPORT_CODES: {
120
119
  readonly INVALID_FIELD_TYPE: "REP_INVALID_FIELD_TYPE";
121
120
  /** Disk write failed during flushToDisk(). */
122
121
  readonly FLUSH_FAILED: "REP_FLUSH_FAILED";
122
+ /**
123
+ * A prior `.sela-history.json` existed on disk but could not be parsed as
124
+ * a JSON array. The merge path refuses to silently overwrite it with a
125
+ * fresh window (which would destroy the rolling history), so it aborts.
126
+ */
127
+ readonly HISTORY_CORRUPT: "REP_HISTORY_CORRUPT";
128
+ /** A shard report file existed but was not valid JSON / had no events array. */
129
+ readonly SHARD_UNREADABLE: "REP_SHARD_UNREADABLE";
123
130
  };
124
131
  export type ReportCode = (typeof REPORT_CODES)[keyof typeof REPORT_CODES];
125
132
  export declare const CHAIN_VALIDATOR_CODES: {
@@ -1 +1 @@
1
- {"version":3,"file":"SelaError.d.ts","sourceRoot":"","sources":["../../src/errors/SelaError.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SelaError.d.ts","sourceRoot":"","sources":["../../src/errors/SelaError.ts"],"names":[],"mappings":"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"}