sela-core 1.0.7 → 1.0.8

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 (114) hide show
  1. package/dist/cli/ErrorHandler.d.ts +1 -1
  2. package/dist/cli/ErrorHandler.js +14 -14
  3. package/dist/cli/commands/bulk.d.ts +1 -1
  4. package/dist/cli/commands/bulk.d.ts.map +1 -1
  5. package/dist/cli/commands/bulk.js +51 -33
  6. package/dist/cli/commands/init.d.ts +1 -1
  7. package/dist/cli/commands/init.d.ts.map +1 -1
  8. package/dist/cli/commands/init.js +26 -18
  9. package/dist/cli/commands/showReport.d.ts +1 -1
  10. package/dist/cli/commands/showReport.d.ts.map +1 -1
  11. package/dist/cli/commands/showReport.js +12 -10
  12. package/dist/cli/commands/status.d.ts +1 -1
  13. package/dist/cli/commands/status.d.ts.map +1 -1
  14. package/dist/cli/commands/status.js +8 -8
  15. package/dist/cli/commands/sync.d.ts +1 -1
  16. package/dist/cli/commands/sync.d.ts.map +1 -1
  17. package/dist/cli/commands/sync.js +38 -30
  18. package/dist/cli/index.js +9 -9
  19. package/dist/cli/ui/DnaTable.d.ts +1 -1
  20. package/dist/cli/ui/DnaTable.d.ts.map +1 -1
  21. package/dist/cli/ui/DnaTable.js +23 -16
  22. package/dist/cli/ui/RefactorWizard.d.ts +3 -3
  23. package/dist/cli/ui/RefactorWizard.d.ts.map +1 -1
  24. package/dist/cli/ui/RefactorWizard.js +108 -82
  25. package/dist/config/ConfigLoader.d.ts +2 -2
  26. package/dist/config/ConfigLoader.d.ts.map +1 -1
  27. package/dist/config/ConfigLoader.js +15 -15
  28. package/dist/config/DryRunGuard.d.ts +1 -1
  29. package/dist/config/DryRunGuard.js +7 -7
  30. package/dist/config/SelaConfig.d.ts +12 -16
  31. package/dist/config/SelaConfig.d.ts.map +1 -1
  32. package/dist/config/SelaConfig.js +32 -26
  33. package/dist/engine/HealingRegistry.d.ts +1 -1
  34. package/dist/engine/HealingRegistry.js +3 -3
  35. package/dist/engine/SelaEngine.d.ts +1 -1
  36. package/dist/engine/SelaEngine.d.ts.map +1 -1
  37. package/dist/engine/SelaEngine.js +63 -49
  38. package/dist/errors/SelaError.d.ts +0 -1
  39. package/dist/errors/SelaError.d.ts.map +1 -1
  40. package/dist/errors/SelaError.js +6 -7
  41. package/dist/fixtures/expectProxy.d.ts +1 -1
  42. package/dist/fixtures/expectProxy.js +11 -11
  43. package/dist/fixtures/index.js +14 -14
  44. package/dist/fixtures/proxyTag.d.ts +1 -1
  45. package/dist/fixtures/proxyTag.js +3 -3
  46. package/dist/index.d.ts +8 -8
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +4 -4
  49. package/dist/reporter/SelaReporter.d.ts +45 -12
  50. package/dist/reporter/SelaReporter.d.ts.map +1 -1
  51. package/dist/reporter/SelaReporter.js +139 -39
  52. package/dist/services/ASTSourceUpdater.d.ts +3 -3
  53. package/dist/services/ASTSourceUpdater.d.ts.map +1 -1
  54. package/dist/services/ASTSourceUpdater.js +92 -68
  55. package/dist/services/ArgumentTypeAnalyzer.js +7 -7
  56. package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -1
  57. package/dist/services/BlastRadiusAnalyzer.js +5 -2
  58. package/dist/services/ChainValidator.js +22 -22
  59. package/dist/services/CrossFileHealer.js +7 -7
  60. package/dist/services/DefinitionTracer.d.ts +1 -1
  61. package/dist/services/DefinitionTracer.d.ts.map +1 -1
  62. package/dist/services/DefinitionTracer.js +28 -13
  63. package/dist/services/DnaEditorService.d.ts +2 -2
  64. package/dist/services/DnaEditorService.d.ts.map +1 -1
  65. package/dist/services/DnaEditorService.js +81 -62
  66. package/dist/services/DnaIndexService.d.ts +1 -1
  67. package/dist/services/DnaIndexService.d.ts.map +1 -1
  68. package/dist/services/DnaIndexService.js +14 -14
  69. package/dist/services/HealReportService.d.ts +6 -6
  70. package/dist/services/HealReportService.d.ts.map +1 -1
  71. package/dist/services/HealReportService.js +33 -29
  72. package/dist/services/HealingAdvisory.js +1 -1
  73. package/dist/services/HealingCacheService.d.ts +8 -8
  74. package/dist/services/HealingCacheService.d.ts.map +1 -1
  75. package/dist/services/HealingCacheService.js +24 -24
  76. package/dist/services/HealthReportService.d.ts +1 -1
  77. package/dist/services/HealthReportService.d.ts.map +1 -1
  78. package/dist/services/HealthReportService.js +25 -25
  79. package/dist/services/InitializerUpdater.js +2 -2
  80. package/dist/services/IntentAuditor.d.ts.map +1 -1
  81. package/dist/services/IntentAuditor.js +32 -21
  82. package/dist/services/InteractiveReview.d.ts +8 -17
  83. package/dist/services/InteractiveReview.d.ts.map +1 -1
  84. package/dist/services/InteractiveReview.js +31 -124
  85. package/dist/services/LLMService.d.ts +1 -1
  86. package/dist/services/LLMService.js +16 -16
  87. package/dist/services/PRAutomationService.d.ts +2 -2
  88. package/dist/services/PRAutomationService.d.ts.map +1 -1
  89. package/dist/services/PRAutomationService.js +43 -39
  90. package/dist/services/PendingPromptLedger.d.ts +2 -2
  91. package/dist/services/PendingPromptLedger.js +6 -6
  92. package/dist/services/ReportGenerator.d.ts +2 -2
  93. package/dist/services/ReportGenerator.d.ts.map +1 -1
  94. package/dist/services/ReportGenerator.js +5 -5
  95. package/dist/services/SafetyGuard.d.ts +3 -6
  96. package/dist/services/SafetyGuard.d.ts.map +1 -1
  97. package/dist/services/SafetyGuard.js +29 -106
  98. package/dist/services/SnapshotService.js +5 -5
  99. package/dist/services/SourceLinkService.d.ts +2 -2
  100. package/dist/services/SourceLinkService.d.ts.map +1 -1
  101. package/dist/services/SourceLinkService.js +31 -22
  102. package/dist/services/SourceUpdater.d.ts +1 -1
  103. package/dist/services/SourceUpdater.d.ts.map +1 -1
  104. package/dist/services/SourceUpdater.js +27 -26
  105. package/dist/services/TemplateDiffService.d.ts.map +1 -1
  106. package/dist/services/TemplateDiffService.js +18 -15
  107. package/dist/services/WorkspaceSnapshotService.d.ts +6 -6
  108. package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -1
  109. package/dist/services/WorkspaceSnapshotService.js +10 -12
  110. package/dist/types/index.d.ts +1 -1
  111. package/dist/utils/IsolatedDiff.d.ts +2 -2
  112. package/dist/utils/IsolatedDiff.d.ts.map +1 -1
  113. package/dist/utils/IsolatedDiff.js +13 -10
  114. package/package.json +2 -2
@@ -50,7 +50,7 @@ const CrossFileHealer_1 = require("./CrossFileHealer");
50
50
  const HealingAdvisory_1 = require("./HealingAdvisory");
51
51
  const ChainValidator_1 = require("./ChainValidator");
52
52
  // ═══════════════════════════════════════════════════════════════════
53
- // FIX #1 normalizeSelector utility
53
+ // FIX #1 - normalizeSelector utility
54
54
  // ═══════════════════════════════════════════════════════════════════
55
55
  function normalizeSelector(s) {
56
56
  return s
@@ -70,7 +70,7 @@ function normalizeSelector(s) {
70
70
  // of "varName", or null otherwise.
71
71
  //
72
72
  // Why this matters:
73
- // const shadowBtn = shadowBtn.getByRole(…) ← CIRCULAR must be caught
73
+ // const shadowBtn = shadowBtn.getByRole(…) ← CIRCULAR - must be caught
74
74
  // const shadowBtn = page.getByRole(…) ← CORRECT
75
75
  //
76
76
  // We walk UP the ancestor chain from the call node looking for a
@@ -83,7 +83,7 @@ function getEnclosingVariableDeclaration(node) {
83
83
  if (ts_morph_1.Node.isVariableDeclaration(current)) {
84
84
  return current;
85
85
  }
86
- // Stop climbing past statement boundaries we only want the immediate
86
+ // Stop climbing past statement boundaries - we only want the immediate
87
87
  // enclosing declaration, not a declaration somewhere further up the tree.
88
88
  if (ts_morph_1.Node.isBlock(current) ||
89
89
  ts_morph_1.Node.isSourceFile(current) ||
@@ -121,7 +121,7 @@ function isInsideOwnInitializer(callNode, varName) {
121
121
  function resolveSafeReceiver(proposedReceiver, rootReceiver, callNode) {
122
122
  if (isInsideOwnInitializer(callNode, proposedReceiver)) {
123
123
  console.log(`[ScopeGuard] 🔒 Circular reference prevented: ` +
124
- `"${proposedReceiver}" is being initialized ` +
124
+ `"${proposedReceiver}" is being initialized - ` +
125
125
  `falling back to root receiver "${rootReceiver}"`);
126
126
  return rootReceiver;
127
127
  }
@@ -554,7 +554,7 @@ class MethodMapper {
554
554
  for (const seg of segments) {
555
555
  const callText = MethodMapper.build(currentReceiver, seg);
556
556
  if (callText === null) {
557
- console.warn(`[MethodMapper] Cannot build segment type "${seg.type}" aborting chain`);
557
+ console.warn(`[MethodMapper] Cannot build segment type "${seg.type}" - aborting chain`);
558
558
  return null;
559
559
  }
560
560
  const methodPart = callText.slice(currentReceiver.length);
@@ -617,7 +617,7 @@ function deduplicateChainSegments(aiSegments, contextSegments) {
617
617
  if (overlap === 0)
618
618
  return { deduped: aiSegments, stripped: 0 };
619
619
  console.log(`[ChainDedup] ✂️ Stripping ${overlap}/${contextSegments.length} duplicate leading ` +
620
- `segment(s) context already encodes them`);
620
+ `segment(s) - context already encodes them`);
621
621
  return { deduped: aiSegments.slice(overlap), stripped: overlap };
622
622
  }
623
623
  const PAGE_ROOT_NAMES = new Set([
@@ -731,15 +731,15 @@ function resolveVariableToSegments(sourceFile, varName, beforeLine, depth = 0) {
731
731
  // Module-level write gate shared between `ASTSourceUpdater` and the
732
732
  // internal `NodeTransformationStrategy`. Centralises three concerns
733
733
  // every `saveSync` call site needs:
734
- // 1. `DryRunGuard.active()` short-circuit keeps the mutation in
734
+ // 1. `DryRunGuard.active()` short-circuit - keeps the mutation in
735
735
  // memory but suppresses the on-disk write under SELA_DRY_RUN.
736
- // 2. `sharedWorkspaceSnapshot.preWrite()` captures `contentBefore`
736
+ // 2. `sharedWorkspaceSnapshot.preWrite()` - captures `contentBefore`
737
737
  // so the Clean-Room ledger / Local DX rollback can rewind.
738
- // 3. `sharedWorkspaceSnapshot.postWrite()` refreshes `contentAfter`
738
+ // 3. `sharedWorkspaceSnapshot.postWrite()` - refreshes `contentAfter`
739
739
  // so `getMutatedSnapshots()` (driving the pending-prompts ledger
740
740
  // and the interactive CLI prompt) sees the new disk state.
741
741
  //
742
- // Strategies do NOT receive the persistence service via DI they call
742
+ // Strategies do NOT receive the persistence service via DI - they call
743
743
  // this helper directly. Same singleton, zero coupling, one code path.
744
744
  // ═══════════════════════════════════════════════════════════════════
745
745
  function persistSourceFile(sourceFile) {
@@ -753,7 +753,7 @@ function persistSourceFile(sourceFile) {
753
753
  WorkspaceSnapshotService_1.sharedWorkspaceSnapshot.postWrite(fp);
754
754
  }
755
755
  // ═══════════════════════════════════════════════════════════════════
756
- // NODE TRANSFORMATION STRATEGY Scope-Aware, Zero-Redundancy
756
+ // NODE TRANSFORMATION STRATEGY - Scope-Aware, Zero-Redundancy
757
757
  // ═══════════════════════════════════════════════════════════════════
758
758
  class NodeTransformationStrategy {
759
759
  chainValidator;
@@ -823,8 +823,10 @@ class NodeTransformationStrategy {
823
823
  // When AI's first segment TYPE matches the receiver variable's defining type
824
824
  // but with a different selector, the AI is replacing the receiver context.
825
825
  // Strategy: update the receiver variable's definition, then use remaining
826
- // segments with the receiver var preserving developer's variable structure.
827
- if (!forcedReceiver && discoveredAstRoot && !PAGE_ROOT_NAMES.has(discoveredAstRoot)) {
826
+ // segments with the receiver var - preserving developer's variable structure.
827
+ if (!forcedReceiver &&
828
+ discoveredAstRoot &&
829
+ !PAGE_ROOT_NAMES.has(discoveredAstRoot)) {
828
830
  const typeCheckRes = resolveVariableToSegments(sourceFile, discoveredAstRoot, caller.line);
829
831
  if (typeCheckRes.segments.length > 0 && workingSegments.length > 0) {
830
832
  const receiverDefType = typeCheckRes.segments[typeCheckRes.segments.length - 1].type;
@@ -923,8 +925,9 @@ class NodeTransformationStrategy {
923
925
  // to prevent. Skip the candidate; the semantic gate owns this case.
924
926
  const firstArg = call.getArguments()[0];
925
927
  if (firstArg &&
926
- (ts_morph_1.Node.isIdentifier(firstArg) || ts_morph_1.Node.isPropertyAccessExpression(firstArg))) {
927
- console.log(`[NodeTransform] 🛑 skip — first arg is ${firstArg.getKindName()} ` +
928
+ (ts_morph_1.Node.isIdentifier(firstArg) ||
929
+ ts_morph_1.Node.isPropertyAccessExpression(firstArg))) {
930
+ console.log(`[NodeTransform] 🛑 skip - first arg is ${firstArg.getKindName()} ` +
928
931
  `"${firstArg.getText()}" (semantic dispatch owns definition-site mutations)`);
929
932
  continue;
930
933
  }
@@ -936,12 +939,12 @@ class NodeTransformationStrategy {
936
939
  // Before we build code, we must verify that the proposed receiver
937
940
  // does not create a circular self-reference.
938
941
  //
939
- // Case A forcedReceiver is set (strip-and-force path):
942
+ // Case A - forcedReceiver is set (strip-and-force path):
940
943
  // Check if the chainTop lives inside the initializer of that var.
941
944
  // If yes, fall back to the actual AST root (e.g. "page").
942
945
  //
943
- // Case B no forced receiver:
944
- // Use astRoot directly it was walked up from the call node and
946
+ // Case B - no forced receiver:
947
+ // Use astRoot directly - it was walked up from the call node and
945
948
  // is always either "page" or a stable variable reference.
946
949
  // ══════════════════════════════════════════════════════════════
947
950
  let effectiveReceiver;
@@ -1191,7 +1194,7 @@ class NodeTransformationStrategy {
1191
1194
  }
1192
1195
  updateReceiverDefinition(sourceFile, varName, segType, newSelector, callerLine) {
1193
1196
  // Collect all matching declarations, then pick the closest one that
1194
- // appears strictly BEFORE callerLine prevents accidentally updating
1197
+ // appears strictly BEFORE callerLine - prevents accidentally updating
1195
1198
  // a same-named variable in a different test block that happens to be
1196
1199
  // within the 100-line distance window.
1197
1200
  const declarations = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.VariableDeclaration);
@@ -1302,7 +1305,7 @@ class NodeTransformationStrategy {
1302
1305
  .map((d) => `[TS${d.getCode()}] ${d.getMessageText()}`)
1303
1306
  .join(", "));
1304
1307
  if (/\.(getBy\w+|frameLocator)\s*\(/.test(code)) {
1305
- console.warn(`[NodeTransform] ⚠️ Semantic method detected bypassing validation`);
1308
+ console.warn(`[NodeTransform] ⚠️ Semantic method detected - bypassing validation`);
1306
1309
  return true;
1307
1310
  }
1308
1311
  return false;
@@ -1562,7 +1565,7 @@ class ASTSourceUpdater {
1562
1565
  /**
1563
1566
  * Centralised write hook for every ts-morph `saveSync` call in this class.
1564
1567
  * When `SELA_DRY_RUN` is active the AST mutation stays in memory but the
1565
- * on-disk file is left untouched the heal pipeline can still compute a
1568
+ * on-disk file is left untouched - the heal pipeline can still compute a
1566
1569
  * candidate diff via `sourceFile.getFullText()` and the report layer
1567
1570
  * tags the event with `dryRun: true`.
1568
1571
  */
@@ -1579,7 +1582,7 @@ class ASTSourceUpdater {
1579
1582
  // BEFORE the LLM call and record a FailedEvent in the "Skipped by
1580
1583
  // Developer" category.
1581
1584
  //
1582
- // Implementation note ts-morph's `Node.getLeadingCommentRanges()`
1585
+ // Implementation note - ts-morph's `Node.getLeadingCommentRanges()`
1583
1586
  // returns `ts.CommentRange[]` (offsets, not text). We slice the full
1584
1587
  // source text by `(pos, end)` to recover the raw comment for each
1585
1588
  // range, matching both `//` line comments and `/* */` block comments
@@ -1643,7 +1646,7 @@ class ASTSourceUpdater {
1643
1646
  return { failFast: false };
1644
1647
  }
1645
1648
  /**
1646
- * Convenience helper runs `scanFailFastDirective` and throws the
1649
+ * Convenience helper - runs `scanFailFastDirective` and throws the
1647
1650
  * canonical SelaError when the directive is present. Used by SelaEngine
1648
1651
  * as the very first gate inside `heal()`.
1649
1652
  */
@@ -1790,7 +1793,7 @@ class ASTSourceUpdater {
1790
1793
  sourceFile = this.project.addSourceFileAtPath(filePath);
1791
1794
  }
1792
1795
  if (caller.line <= 0) {
1793
- console.log(`[ASTUpdater] ⚠️ line ${caller.line} invalid Attempting Global Template Strategy`);
1796
+ console.log(`[ASTUpdater] ⚠️ line ${caller.line} invalid - Attempting Global Template Strategy`);
1794
1797
  const globalResult = this.strategyTemplateLiteral(sourceFile, caller, oldSelector, newSelector);
1795
1798
  if (globalResult && globalResult.success) {
1796
1799
  if (contentChange)
@@ -1814,7 +1817,7 @@ class ASTSourceUpdater {
1814
1817
  // node when they differ) for `// sela-fail-fast`. When present, abort
1815
1818
  // all heal work with SelaError(AST_HEAL_DISABLED_BY_DIRECTIVE) so the
1816
1819
  // engine records a FailedEvent in the "Skipped by Developer" bucket.
1817
- // Defense-in-depth SelaEngine also calls this at the very start of
1820
+ // Defense-in-depth - SelaEngine also calls this at the very start of
1818
1821
  // heal() to skip the LLM round-trip entirely.
1819
1822
  this.enforceFailFastDirective(caller);
1820
1823
  const suspectIdentifier = statement
@@ -1827,7 +1830,7 @@ class ASTSourceUpdater {
1827
1830
  // HARD EXIT: any non-null result (success OR failure) stops all
1828
1831
  // subsequent AST strategies. When the locator argument is an
1829
1832
  // Identifier, PropertyAccess, or TemplateLiteral, the gate owns
1830
- // the mutation NT/H must never override the symbolic reference.
1833
+ // the mutation - NT/H must never override the symbolic reference.
1831
1834
  const semanticResult = this.semanticDispatch(sourceFile, caller, oldSelector, newSelector);
1832
1835
  if (semanticResult !== null) {
1833
1836
  if (semanticResult.success) {
@@ -1836,7 +1839,7 @@ class ASTSourceUpdater {
1836
1839
  }
1837
1840
  return this.broadcastAndReturn(semanticResult, oldSelector, newSelector, caller);
1838
1841
  }
1839
- // Failure (blast-radius block, trace failed, syntax error) hard stop.
1842
+ // Failure (blast-radius block, trace failed, syntax error) - hard stop.
1840
1843
  console.log(`[SemanticDispatch] 🚫 Hard stop (${semanticResult.strategy}): ${semanticResult.reason}`);
1841
1844
  return semanticResult;
1842
1845
  }
@@ -1885,7 +1888,7 @@ class ASTSourceUpdater {
1885
1888
  };
1886
1889
  }
1887
1890
  // ═══════════════════════════════════════════════════════════════
1888
- // STRATEGY H Smart Chain (Legacy fallback)
1891
+ // STRATEGY H - Smart Chain (Legacy fallback)
1889
1892
  // ═══════════════════════════════════════════════════════════════
1890
1893
  strategySmartChain(sourceFile, caller, oldSelector, oldSem, smartSegments, originalChainHint, suspectIdentifier) {
1891
1894
  console.log(`[ASTUpdater] 🔗 Strategy H v2: Smart Chain (${smartSegments.length} segments)`);
@@ -1959,13 +1962,14 @@ class ASTSourceUpdater {
1959
1962
  return b.chainDepth - a.chainDepth;
1960
1963
  });
1961
1964
  for (const { leafCall, chainTop, rootReceiver, chainDepth, originalText, } of candidates) {
1962
- // Identifier/PropertyAccess guard mirrors the NT guard.
1965
+ // Identifier/PropertyAccess guard - mirrors the NT guard.
1963
1966
  // Strategy H must never substitute a hardcoded string for a symbolic
1964
1967
  // reference; the semantic dispatch gate owns definition-site mutations.
1965
1968
  const firstArgH = leafCall.getArguments()[0];
1966
1969
  if (firstArgH &&
1967
- (ts_morph_1.Node.isIdentifier(firstArgH) || ts_morph_1.Node.isPropertyAccessExpression(firstArgH))) {
1968
- console.log(`[StrategyH] 🛑 skip — first arg is ${firstArgH.getKindName()} ` +
1970
+ (ts_morph_1.Node.isIdentifier(firstArgH) ||
1971
+ ts_morph_1.Node.isPropertyAccessExpression(firstArgH))) {
1972
+ console.log(`[StrategyH] 🛑 skip - first arg is ${firstArgH.getKindName()} ` +
1969
1973
  `"${firstArgH.getText()}" (semantic dispatch owns definition-site mutations)`);
1970
1974
  continue;
1971
1975
  }
@@ -2035,8 +2039,9 @@ class ASTSourceUpdater {
2035
2039
  // Block H-partial from substituting a literal for an Identifier/PropertyAccess arg.
2036
2040
  const targetFirstArg = targetCall.getArguments()[0];
2037
2041
  if (targetFirstArg &&
2038
- (ts_morph_1.Node.isIdentifier(targetFirstArg) || ts_morph_1.Node.isPropertyAccessExpression(targetFirstArg))) {
2039
- console.log(`[H-partial] 🛑 skip — arg is ${targetFirstArg.getKindName()} ` +
2042
+ (ts_morph_1.Node.isIdentifier(targetFirstArg) ||
2043
+ ts_morph_1.Node.isPropertyAccessExpression(targetFirstArg))) {
2044
+ console.log(`[H-partial] 🛑 skip - arg is ${targetFirstArg.getKindName()} ` +
2040
2045
  `"${targetFirstArg.getText()}" (semantic dispatch owns this)`);
2041
2046
  return null;
2042
2047
  }
@@ -2072,7 +2077,7 @@ class ASTSourceUpdater {
2072
2077
  }
2073
2078
  }
2074
2079
  // ─────────────────────────────────────────────────────────────
2075
- // STRATEGY F Chain Collapse
2080
+ // STRATEGY F - Chain Collapse
2076
2081
  // ─────────────────────────────────────────────────────────────
2077
2082
  strategyChainCollapse(sourceFile, caller, oldSelector, newSelector, oldSem, newSem) {
2078
2083
  console.log(`[ASTUpdater] ⛓️ Strategy F: Chain Collapse (upward traversal)`);
@@ -2138,7 +2143,7 @@ class ASTSourceUpdater {
2138
2143
  };
2139
2144
  }
2140
2145
  // ─────────────────────────────────────────────────────────────
2141
- // STRATEGY G Assertion Healing
2146
+ // STRATEGY G - Assertion Healing
2142
2147
  // ─────────────────────────────────────────────────────────────
2143
2148
  runStrategyG(sourceFile, caller, locatorVarName, contentChange) {
2144
2149
  if (!contentChange)
@@ -2170,7 +2175,7 @@ class ASTSourceUpdater {
2170
2175
  return null;
2171
2176
  }
2172
2177
  // ─────────────────────────────────────────────────────────────
2173
- // STRATEGY A Frame Upstream Healing
2178
+ // STRATEGY A - Frame Upstream Healing
2174
2179
  // ─────────────────────────────────────────────────────────────
2175
2180
  strategyFrameUpstream(sourceFile, caller, oldElementSelector, aiSegments, fullSelectorContext) {
2176
2181
  console.log(`[ASTUpdater] 🧠 Strategy A: Frame Upstream`);
@@ -2246,7 +2251,7 @@ class ASTSourceUpdater {
2246
2251
  };
2247
2252
  }
2248
2253
  // ─────────────────────────────────────────────────────────────
2249
- // STRATEGY B Deep Symbol Resolution
2254
+ // STRATEGY B - Deep Symbol Resolution
2250
2255
  // ─────────────────────────────────────────────────────────────
2251
2256
  strategyDeepSymbolResolution(sourceFile, caller, oldSelector, newSelector, oldSem, newSem, suspectIdentifier) {
2252
2257
  console.log(`[ASTUpdater] 🔭 Strategy B: Deep Symbol Resolution`);
@@ -2430,7 +2435,7 @@ class ASTSourceUpdater {
2430
2435
  };
2431
2436
  }
2432
2437
  // ─────────────────────────────────────────────────────────────
2433
- // STRATEGY C Inline Semantic Fix
2438
+ // STRATEGY C - Inline Semantic Fix
2434
2439
  // ─────────────────────────────────────────────────────────────
2435
2440
  strategyInlineSemanticFix(sourceFile, caller, oldSelector, newSelector, oldSem, newSem) {
2436
2441
  console.log(`[ASTUpdater] 🎯 Strategy C: Inline Semantic Fix`);
@@ -2488,7 +2493,7 @@ class ASTSourceUpdater {
2488
2493
  };
2489
2494
  }
2490
2495
  // ─────────────────────────────────────────────────────────────
2491
- // STRATEGY D Template Literal
2496
+ // STRATEGY D - Template Literal
2492
2497
  // ─────────────────────────────────────────────────────────────
2493
2498
  strategyTemplateLiteral(sourceFile, caller, oldSelector, newSelector) {
2494
2499
  console.log(`[ASTUpdater] 🔤 Strategy D: Template Literal`);
@@ -2545,7 +2550,7 @@ class ASTSourceUpdater {
2545
2550
  };
2546
2551
  }
2547
2552
  // ─────────────────────────────────────────────────────────────
2548
- // STRATEGY E Semantic Fragment Scan
2553
+ // STRATEGY E - Semantic Fragment Scan
2549
2554
  // ─────────────────────────────────────────────────────────────
2550
2555
  strategySemanticFragmentScan(sourceFile, caller, oldSelector, newSelector, oldSem, newSem) {
2551
2556
  console.log(`[ASTUpdater] 🔎 Strategy E: Semantic Fragment Scan`);
@@ -2666,7 +2671,7 @@ class ASTSourceUpdater {
2666
2671
  /**
2667
2672
  * Guard: returns false when replacing oldNode with proposedNewText would
2668
2673
  * substitute a hardcoded string literal for an Identifier or
2669
- * PropertyAccessExpression which is the definition-site mutation bug.
2674
+ * PropertyAccessExpression - which is the definition-site mutation bug.
2670
2675
  * All other replacements are allowed.
2671
2676
  */
2672
2677
  static isSafeReplacement(oldNode, proposedNewText) {
@@ -2690,7 +2695,7 @@ class ASTSourceUpdater {
2690
2695
  firstArg.replaceWithText(`"${safe}"`);
2691
2696
  }
2692
2697
  else {
2693
- console.warn(`[ASTUpdater] ⚠️ replaceCallArgument: blocked unsafe replacement ` +
2698
+ console.warn(`[ASTUpdater] ⚠️ replaceCallArgument: blocked unsafe replacement - ` +
2694
2699
  `arg is ${firstArg.getKindName()}, not a string literal. ` +
2695
2700
  `Heal at definition site instead.`);
2696
2701
  return false;
@@ -2992,10 +2997,10 @@ class ASTSourceUpdater {
2992
2997
  shape === "PROPERTY_ACCESS" ||
2993
2998
  shape === "TEMPLATE_LITERAL") {
2994
2999
  console.log(`[SemanticDispatch] 🛑 hard-block: "${node.getText()}" is ${shape} ` +
2995
- `but trace failed preserving call site`);
3000
+ `but trace failed - preserving call site`);
2996
3001
  return {
2997
3002
  success: false,
2998
- reason: `semantic guard: could not trace "${node.getText()}" call site preserved`,
3003
+ reason: `semantic guard: could not trace "${node.getText()}" - call site preserved`,
2999
3004
  strategy: "semantic-guard",
3000
3005
  };
3001
3006
  }
@@ -3018,21 +3023,21 @@ class ASTSourceUpdater {
3018
3023
  if (blast.risk === "high") {
3019
3024
  this.advisoryBuffer.push({
3020
3025
  code: HealingAdvisory_1.AdvisoryCode.BLAST_RADIUS_BLOCKED,
3021
- message: `Mutation blocked ${blast.testFunctionCount} tests reference this constant.`,
3026
+ message: `Mutation blocked - ${blast.testFunctionCount} tests reference this constant.`,
3022
3027
  affectedFile: targetFile.getFilePath(),
3023
3028
  affectedLine: targetNode.getStartLineNumber() - 1,
3024
3029
  suggestedAction: "Review all referencing tests before changing this constant.",
3025
3030
  });
3026
3031
  return {
3027
3032
  success: false,
3028
- reason: `BlastRadius BLOCKED: ${blast.testFunctionCount} tests reference this constant manual review required`,
3033
+ reason: `BlastRadius BLOCKED: ${blast.testFunctionCount} tests reference this constant - manual review required`,
3029
3034
  strategy: "semantic-identifier",
3030
3035
  };
3031
3036
  }
3032
3037
  if (blast.risk === "medium") {
3033
3038
  this.advisoryBuffer.push({
3034
3039
  code: HealingAdvisory_1.AdvisoryCode.BLAST_RADIUS_WARNING,
3035
- message: `Mutated constant used in ${blast.testFunctionCount} tests verify no regressions.`,
3040
+ message: `Mutated constant used in ${blast.testFunctionCount} tests - verify no regressions.`,
3036
3041
  affectedFile: targetFile.getFilePath(),
3037
3042
  affectedLine: targetNode.getStartLineNumber() - 1,
3038
3043
  suggestedAction: "Run the full test suite to confirm all references still pass.",
@@ -3044,7 +3049,7 @@ class ASTSourceUpdater {
3044
3049
  if (!this.validateFileSyntax(targetFile)) {
3045
3050
  return {
3046
3051
  success: false,
3047
- reason: "post-mutation syntax validation failed reverted",
3052
+ reason: "post-mutation syntax validation failed - reverted",
3048
3053
  strategy: "semantic-identifier",
3049
3054
  };
3050
3055
  }
@@ -3054,7 +3059,10 @@ class ASTSourceUpdater {
3054
3059
  strategy: "semantic-identifier",
3055
3060
  lineUpdated: result.lineUpdated,
3056
3061
  healedLocatorString: result.healedLocatorString,
3057
- definitionSite: { file: targetFile.getFilePath(), line: result.lineUpdated },
3062
+ definitionSite: {
3063
+ file: targetFile.getFilePath(),
3064
+ line: result.lineUpdated,
3065
+ },
3058
3066
  blastRadius: blast.testFunctionCount,
3059
3067
  };
3060
3068
  }
@@ -3083,21 +3091,21 @@ class ASTSourceUpdater {
3083
3091
  if (blast.risk === "high") {
3084
3092
  this.advisoryBuffer.push({
3085
3093
  code: HealingAdvisory_1.AdvisoryCode.BLAST_RADIUS_BLOCKED,
3086
- message: `Mutation blocked ${blast.testFunctionCount} tests reference this property.`,
3094
+ message: `Mutation blocked - ${blast.testFunctionCount} tests reference this property.`,
3087
3095
  affectedFile: targetFile.getFilePath(),
3088
3096
  affectedLine: targetNode.getStartLineNumber() - 1,
3089
3097
  suggestedAction: "Review all referencing tests before changing this property.",
3090
3098
  });
3091
3099
  return {
3092
3100
  success: false,
3093
- reason: `BlastRadius BLOCKED: ${blast.testFunctionCount} tests reference this property manual review required`,
3101
+ reason: `BlastRadius BLOCKED: ${blast.testFunctionCount} tests reference this property - manual review required`,
3094
3102
  strategy: "semantic-property-access",
3095
3103
  };
3096
3104
  }
3097
3105
  if (blast.risk === "medium") {
3098
3106
  this.advisoryBuffer.push({
3099
3107
  code: HealingAdvisory_1.AdvisoryCode.BLAST_RADIUS_WARNING,
3100
- message: `Mutated property used in ${blast.testFunctionCount} tests verify no regressions.`,
3108
+ message: `Mutated property used in ${blast.testFunctionCount} tests - verify no regressions.`,
3101
3109
  affectedFile: targetFile.getFilePath(),
3102
3110
  affectedLine: targetNode.getStartLineNumber() - 1,
3103
3111
  suggestedAction: "Run the full test suite to confirm all references still pass.",
@@ -3109,7 +3117,7 @@ class ASTSourceUpdater {
3109
3117
  if (!this.validateFileSyntax(targetFile)) {
3110
3118
  return {
3111
3119
  success: false,
3112
- reason: "post-mutation syntax validation failed reverted",
3120
+ reason: "post-mutation syntax validation failed - reverted",
3113
3121
  strategy: "semantic-property-access",
3114
3122
  };
3115
3123
  }
@@ -3119,7 +3127,10 @@ class ASTSourceUpdater {
3119
3127
  strategy: "semantic-property-access",
3120
3128
  lineUpdated: result.lineUpdated,
3121
3129
  healedLocatorString: result.healedLocatorString,
3122
- definitionSite: { file: targetFile.getFilePath(), line: result.lineUpdated },
3130
+ definitionSite: {
3131
+ file: targetFile.getFilePath(),
3132
+ line: result.lineUpdated,
3133
+ },
3123
3134
  blastRadius: blast.testFunctionCount,
3124
3135
  };
3125
3136
  }
@@ -3163,10 +3174,11 @@ class ASTSourceUpdater {
3163
3174
  }
3164
3175
  }
3165
3176
  }
3166
- if (patchResult.reason.includes("structural") || patchResult.reason.includes("not found")) {
3177
+ if (patchResult.reason.includes("structural") ||
3178
+ patchResult.reason.includes("not found")) {
3167
3179
  this.advisoryBuffer.push({
3168
3180
  code: HealingAdvisory_1.AdvisoryCode.MANUAL_REVIEW_TEMPLATE_COMPLEX,
3169
- message: `Template literal requires structural change automated patch skipped.`,
3181
+ message: `Template literal requires structural change - automated patch skipped.`,
3170
3182
  affectedFile: sourceFile.getFilePath(),
3171
3183
  affectedLine: node.getStartLineNumber() - 1,
3172
3184
  suggestedAction: "Manually update the template literal and its callers.",
@@ -3180,7 +3192,7 @@ class ASTSourceUpdater {
3180
3192
  if (!this.validateFileSyntax(sourceFile)) {
3181
3193
  return {
3182
3194
  success: false,
3183
- reason: "post-mutation syntax validation failed reverted",
3195
+ reason: "post-mutation syntax validation failed - reverted",
3184
3196
  strategy: "semantic-template",
3185
3197
  };
3186
3198
  }
@@ -3208,7 +3220,8 @@ class ASTSourceUpdater {
3208
3220
  if (ts_morph_1.Node.isCallExpression(init)) {
3209
3221
  return this.handleCallExpressionArg(init, sourceFile, oldSpanVal, newSpanVal);
3210
3222
  }
3211
- if (ts_morph_1.Node.isStringLiteral(init) || ts_morph_1.Node.isNoSubstitutionTemplateLiteral(init)) {
3223
+ if (ts_morph_1.Node.isStringLiteral(init) ||
3224
+ ts_morph_1.Node.isNoSubstitutionTemplateLiteral(init)) {
3212
3225
  const result = InitializerUpdater_1.InitializerUpdater.apply(init, sourceFile, newSpanVal);
3213
3226
  if (!result)
3214
3227
  return null;
@@ -3219,7 +3232,10 @@ class ASTSourceUpdater {
3219
3232
  strategy: "semantic-template",
3220
3233
  lineUpdated: result.lineUpdated,
3221
3234
  healedLocatorString: result.healedLocatorString,
3222
- definitionSite: { file: sourceFile.getFilePath(), line: result.lineUpdated },
3235
+ definitionSite: {
3236
+ file: sourceFile.getFilePath(),
3237
+ line: result.lineUpdated,
3238
+ },
3223
3239
  };
3224
3240
  }
3225
3241
  if (ts_morph_1.Node.isTemplateExpression(init)) {
@@ -3233,7 +3249,7 @@ class ASTSourceUpdater {
3233
3249
  if (fnAnalysis.kind === "complex") {
3234
3250
  this.advisoryBuffer.push({
3235
3251
  code: HealingAdvisory_1.AdvisoryCode.MANUAL_REVIEW_CONDITIONAL_RETURN,
3236
- message: `Function has conditional/complex return automated patch skipped. Reason: ${fnAnalysis.reason}`,
3252
+ message: `Function has conditional/complex return - automated patch skipped. Reason: ${fnAnalysis.reason}`,
3237
3253
  affectedFile: sourceFile.getFilePath(),
3238
3254
  suggestedAction: "Manually update the function's return expression.",
3239
3255
  });
@@ -3246,7 +3262,7 @@ class ASTSourceUpdater {
3246
3262
  if (!this.validateFileSyntax(fnAnalysis.functionFile)) {
3247
3263
  return {
3248
3264
  success: false,
3249
- reason: "post-mutation syntax validation failed reverted",
3265
+ reason: "post-mutation syntax validation failed - reverted",
3250
3266
  strategy: "semantic-call-expression",
3251
3267
  };
3252
3268
  }
@@ -3256,7 +3272,10 @@ class ASTSourceUpdater {
3256
3272
  strategy: "semantic-call-expression",
3257
3273
  lineUpdated: result.lineUpdated,
3258
3274
  healedLocatorString: result.healedLocatorString,
3259
- definitionSite: { file: fnAnalysis.functionFile.getFilePath(), line: result.lineUpdated },
3275
+ definitionSite: {
3276
+ file: fnAnalysis.functionFile.getFilePath(),
3277
+ line: result.lineUpdated,
3278
+ },
3260
3279
  };
3261
3280
  }
3262
3281
  if (fnAnalysis.kind === "template") {
@@ -3266,7 +3285,7 @@ class ASTSourceUpdater {
3266
3285
  if (patchResult.reason.includes("structural")) {
3267
3286
  this.advisoryBuffer.push({
3268
3287
  code: HealingAdvisory_1.AdvisoryCode.MANUAL_REVIEW_TEMPLATE_COMPLEX,
3269
- message: `Function template return requires structural change automated patch skipped.`,
3288
+ message: `Function template return requires structural change - automated patch skipped.`,
3270
3289
  affectedFile: fnAnalysis.functionFile.getFilePath(),
3271
3290
  affectedLine: fnAnalysis.functionLine - 1,
3272
3291
  suggestedAction: "Manually update the function's template literal.",
@@ -3280,7 +3299,7 @@ class ASTSourceUpdater {
3280
3299
  if (!this.validateFileSyntax(fnAnalysis.functionFile)) {
3281
3300
  return {
3282
3301
  success: false,
3283
- reason: "post-mutation syntax validation failed reverted",
3302
+ reason: "post-mutation syntax validation failed - reverted",
3284
3303
  strategy: "semantic-call-expression",
3285
3304
  };
3286
3305
  }
@@ -3290,7 +3309,10 @@ class ASTSourceUpdater {
3290
3309
  strategy: "semantic-call-expression",
3291
3310
  lineUpdated,
3292
3311
  healedLocatorString: newSelector,
3293
- definitionSite: { file: fnAnalysis.functionFile.getFilePath(), line: lineUpdated },
3312
+ definitionSite: {
3313
+ file: fnAnalysis.functionFile.getFilePath(),
3314
+ line: lineUpdated,
3315
+ },
3294
3316
  };
3295
3317
  }
3296
3318
  return null;
@@ -3306,11 +3328,13 @@ class ASTSourceUpdater {
3306
3328
  return !ALLOWED_CODES.has(d.getCode());
3307
3329
  });
3308
3330
  if (syntaxErrors.length > 0) {
3309
- const msgs = syntaxErrors.map((d) => String(d.getMessageText())).join("; ");
3310
- console.warn(`[SemanticDispatch] ⚠️ syntax errors after mutation: ${msgs} — reverting`);
3331
+ const msgs = syntaxErrors
3332
+ .map((d) => String(d.getMessageText()))
3333
+ .join("; ");
3334
+ console.warn(`[SemanticDispatch] ⚠️ syntax errors after mutation: ${msgs} - reverting`);
3311
3335
  this.advisoryBuffer.push({
3312
3336
  code: HealingAdvisory_1.AdvisoryCode.POST_MUTATION_TYPE_ERROR,
3313
- message: `Post-mutation type errors detected mutation reverted. Errors: ${msgs}`,
3337
+ message: `Post-mutation type errors detected - mutation reverted. Errors: ${msgs}`,
3314
3338
  affectedFile: sourceFile.getFilePath(),
3315
3339
  suggestedAction: "Manually inspect and fix the type errors introduced by this heal.",
3316
3340
  });
@@ -20,7 +20,7 @@ exports.ALL_LOCATOR_METHODS = new Set([
20
20
  // ArgumentTypeAnalyzer
21
21
  //
22
22
  // Classifies the first argument of a Playwright locator CallExpression.
23
- // Stateless no file I/O, no side effects.
23
+ // Stateless - no file I/O, no side effects.
24
24
  // ═══════════════════════════════════════════════════════════════════
25
25
  class ArgumentTypeAnalyzer {
26
26
  /**
@@ -64,28 +64,28 @@ class ArgumentTypeAnalyzer {
64
64
  // Private helpers
65
65
  // ─────────────────────────────────────────────────────────────────
66
66
  static classifyNode(node) {
67
- // Plain string value is self-contained in this node.
67
+ // Plain string - value is self-contained in this node.
68
68
  if (ts_morph_1.Node.isStringLiteral(node) ||
69
69
  ts_morph_1.Node.isNoSubstitutionTemplateLiteral(node)) {
70
70
  return "STRING_LITERAL";
71
71
  }
72
- // Template with ${...} spans static segments are healable, spans are not.
72
+ // Template with ${...} spans - static segments are healable, spans are not.
73
73
  if (ts_morph_1.Node.isTemplateExpression(node)) {
74
74
  return "TEMPLATE_LITERAL";
75
75
  }
76
- // Bare variable name must trace to declaration.
76
+ // Bare variable name - must trace to declaration.
77
77
  if (ts_morph_1.Node.isIdentifier(node)) {
78
78
  return "IDENTIFIER";
79
79
  }
80
- // OBJECT.property must trace to object literal property value.
80
+ // OBJECT.property - must trace to object literal property value.
81
81
  if (ts_morph_1.Node.isPropertyAccessExpression(node)) {
82
82
  return "PROPERTY_ACCESS";
83
83
  }
84
- // fn(...) must enter function body to find return value.
84
+ // fn(...) - must enter function body to find return value.
85
85
  if (ts_morph_1.Node.isCallExpression(node)) {
86
86
  return "CALL_EXPRESSION";
87
87
  }
88
- // Binary expressions, conditionals, spreads, etc. not healable here.
88
+ // Binary expressions, conditionals, spreads, etc. - not healable here.
89
89
  return "COMPLEX";
90
90
  }
91
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BlastRadiusAnalyzer.d.ts","sourceRoot":"","sources":["../../src/services/BlastRadiusAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAc,MAAM,UAAU,CAAC;AAMjE,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,SAAS,CAAC;CACjB;AAWD,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,OAAO,CACZ,eAAe,EAAE,IAAI,EACrB,WAAW,EAAE,UAAU,EACvB,QAAQ,EAAE,OAAO,GAChB,iBAAiB;IAgBpB,OAAO,CAAC,MAAM,CAAC,SAAS;IAwDxB,OAAO,CAAC,MAAM,CAAC,WAAW;IAY1B,OAAO,CAAC,MAAM,CAAC,UAAU;CAiB1B"}
1
+ {"version":3,"file":"BlastRadiusAnalyzer.d.ts","sourceRoot":"","sources":["../../src/services/BlastRadiusAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAc,MAAM,UAAU,CAAC;AAMjE,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,SAAS,CAAC;CACjB;AAWD,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,OAAO,CACZ,eAAe,EAAE,IAAI,EACrB,WAAW,EAAE,UAAU,EACvB,QAAQ,EAAE,OAAO,GAChB,iBAAiB;IAgBpB,OAAO,CAAC,MAAM,CAAC,SAAS;IA2DxB,OAAO,CAAC,MAAM,CAAC,WAAW;IAY1B,OAAO,CAAC,MAAM,CAAC,UAAU;CAiB1B"}
@@ -8,7 +8,7 @@ const ts_morph_1 = require("ts-morph");
8
8
  // Before mutating a definition-site node, determine how many tests
9
9
  // reference it. Uses ts-morph's findReferences() for cross-file
10
10
  // accuracy. On any analysis failure, defaults to risk:'low' and logs
11
- // a warning never blocks healing due to analysis error.
11
+ // a warning - never blocks healing due to analysis error.
12
12
  // ═══════════════════════════════════════════════════════════════════
13
13
  class BlastRadiusAnalyzer {
14
14
  static analyze(declarationNode, _sourceFile, _project) {
@@ -35,7 +35,10 @@ class BlastRadiusAnalyzer {
35
35
  risk: "low",
36
36
  };
37
37
  }
38
- const refs = nameNode.getProject().getLanguageService().findReferences(nameNode);
38
+ const refs = nameNode
39
+ .getProject()
40
+ .getLanguageService()
41
+ .findReferences(nameNode);
39
42
  const affectedFilesSet = new Set();
40
43
  let totalRefs = 0;
41
44
  // Key = filePath:startLine of the enclosing test() / it() call.