sela-core 0.1.0-alpha.36 → 0.1.0-alpha.37

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.
@@ -10,5 +10,20 @@ export declare const DryRunGuard: {
10
10
  * and a real run is auditable in test output and CI logs.
11
11
  */
12
12
  logSkippedWrite(label: string, target: string): void;
13
+ /**
14
+ * Run `fn` with the dry-run gate forcibly ACTIVE, restoring the prior
15
+ * `SELA_DRY_RUN` value afterwards. Every write-head consulted by `fn`
16
+ * (SourceUpdater, ASTSourceUpdater, InitializerUpdater, CrossFileHealer,
17
+ * git auto-commit) sees `active() === true` and skips its disk write, so
18
+ * the scope is a hard zero-write guarantee — used for speculative
19
+ * "what would the heal look like" previews (e.g. the shared-locator
20
+ * bypass ghost diff) that must compute a mutation in memory without
21
+ * touching the source tree.
22
+ *
23
+ * Safe under Sela's execution model: heals are awaited serially within a
24
+ * worker and Playwright workers are separate processes, so the transient
25
+ * env mutation cannot leak across a concurrent heal.
26
+ */
27
+ runSuppressed<T>(fn: () => Promise<T> | T): Promise<T>;
13
28
  };
14
29
  //# sourceMappingURL=DryRunGuard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DryRunGuard.d.ts","sourceRoot":"","sources":["../../src/config/DryRunGuard.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,WAAW;IACtB;;;;OAIG;iBACS,MAAM,CAAC,UAAU,GAAiB,OAAO;IAIrD;;;OAGG;2BACoB,MAAM,UAAU,MAAM,GAAG,IAAI;CAIrD,CAAC"}
1
+ {"version":3,"file":"DryRunGuard.d.ts","sourceRoot":"","sources":["../../src/config/DryRunGuard.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,WAAW;IACtB;;;;OAIG;iBACS,MAAM,CAAC,UAAU,GAAiB,OAAO;IAIrD;;;OAGG;2BACoB,MAAM,UAAU,MAAM,GAAG,IAAI;IAKpD;;;;;;;;;;;;;OAaG;kBACiB,CAAC,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAa7D,CAAC"}
@@ -77,4 +77,34 @@ exports.DryRunGuard = {
77
77
  const display = target ? path.basename(target) : "<no-path>";
78
78
  logger_1.logger.debug(`Dry Run - skip ${label} → ${display}`);
79
79
  },
80
+ /**
81
+ * Run `fn` with the dry-run gate forcibly ACTIVE, restoring the prior
82
+ * `SELA_DRY_RUN` value afterwards. Every write-head consulted by `fn`
83
+ * (SourceUpdater, ASTSourceUpdater, InitializerUpdater, CrossFileHealer,
84
+ * git auto-commit) sees `active() === true` and skips its disk write, so
85
+ * the scope is a hard zero-write guarantee — used for speculative
86
+ * "what would the heal look like" previews (e.g. the shared-locator
87
+ * bypass ghost diff) that must compute a mutation in memory without
88
+ * touching the source tree.
89
+ *
90
+ * Safe under Sela's execution model: heals are awaited serially within a
91
+ * worker and Playwright workers are separate processes, so the transient
92
+ * env mutation cannot leak across a concurrent heal.
93
+ */
94
+ async runSuppressed(fn) {
95
+ const prev = process.env.SELA_DRY_RUN;
96
+ // Must be the strict token `parseEnvBoolean` accepts ("true"/"false") —
97
+ // "1" throws. MutationApplier is additionally pinned with write:false by
98
+ // callers, so its `=== "1"` dry-run check is not relied upon here.
99
+ process.env.SELA_DRY_RUN = "true";
100
+ try {
101
+ return await fn();
102
+ }
103
+ finally {
104
+ if (prev === undefined)
105
+ delete process.env.SELA_DRY_RUN;
106
+ else
107
+ process.env.SELA_DRY_RUN = prev;
108
+ }
109
+ },
80
110
  };
@@ -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;AAcxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,EAAe,QAAQ,EAAkB,MAAM,yBAAyB,CAAC;AAiGhF,qBAAa,UAAU;IACrB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,oBAAoB,CAAuB;IACnD,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;IAKzD,OAAO,CAAC,qBAAqB,CAAkC;;IA0BzD,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;IAqEnB,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;IA06BlB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;IAerB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,2BAA2B;IA4BnC,OAAO,CAAC,yBAAyB;IAgDjC,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;IAI5E,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK/B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;YAsJtB,aAAa;IAsB3B,OAAO,CAAC,0BAA0B;IA+BlC,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;AAcxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,EAAe,QAAQ,EAAkB,MAAM,yBAAyB,CAAC;AAiGhF,qBAAa,UAAU;IACrB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,oBAAoB,CAAuB;IACnD,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;IAKzD,OAAO,CAAC,qBAAqB,CAAkC;;IA0BzD,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;IAqEnB,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;IAm9BlB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;IAerB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,2BAA2B;IA4BnC,OAAO,CAAC,yBAAyB;IAgDjC,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;IAI5E,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK/B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;YAsJtB,aAAa;IAsB3B,OAAO,CAAC,0BAA0B;IA+BlC,OAAO,CAAC,WAAW;IA6Bb,wBAAwB,CAC5B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CAqBnB;AAED,OAAO,EAAE,CAAC"}
@@ -586,7 +586,41 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
586
586
  line,
587
587
  });
588
588
  if (census.shared) {
589
- const ghostDiff = (0, IsolatedDiff_1.generateUnifiedDiff)(`${diskOldElementSelector}\n`, `${diskNewSelector}\n`, { filePath: census.variablePath, context: 1, normalizeEol: true });
589
+ // ROOT-DECLARATION GHOST DIFF (zero-write): reuse the same AST heal
590
+ // engine HEALED events use, in a suppressed dry-run preview, so the
591
+ // bypass card shows the elegant declaration-root mutation (uniform
592
+ // with HEALED) instead of a raw selector-string swap. Falls back to
593
+ // the legacy selector diff if the engine can't resolve a root.
594
+ let ghostDiff = "";
595
+ let previewDeclSite;
596
+ try {
597
+ const preview = await ASTSourceUpdater_1.ASTSourceUpdater.composeHealPreview({
598
+ filePath: resolvedForCompose ?? filePath,
599
+ line,
600
+ newSelector: diskNewSelector,
601
+ oldSelector: diskOldElementSelector,
602
+ });
603
+ ghostDiff = preview.ghostDiff;
604
+ previewDeclSite = preview.definitionSite;
605
+ }
606
+ catch (err) {
607
+ logger_1.logger.debug(`Bypass root-diff preview failed, using fallback: ${err?.message ?? err}`);
608
+ }
609
+ if (!ghostDiff) {
610
+ ghostDiff = (0, IsolatedDiff_1.generateUnifiedDiff)(`${diskOldElementSelector}\n`, `${diskNewSelector}\n`, { filePath: census.variablePath, context: 1, normalizeEol: true });
611
+ }
612
+ // Declaration locus for the HTML highlight. census.variablePath is
613
+ // "relative/path.ts:LINE"; prefer the preview's resolved site (gives
614
+ // an accurate cross-file path) when available.
615
+ const declColon = census.variablePath.lastIndexOf(":");
616
+ const declarationFile = previewDeclSite?.file ??
617
+ (declColon > 1
618
+ ? census.variablePath.slice(0, declColon)
619
+ : census.variablePath);
620
+ const declarationLine = previewDeclSite?.line ??
621
+ (declColon > 1
622
+ ? Number(census.variablePath.slice(declColon + 1)) || undefined
623
+ : undefined);
590
624
  const message = `Sela Safety Guard: this locator is tied to a shared declaration at ` +
591
625
  `${census.variablePath}, referenced by ${census.testFunctionCount} test(s). ` +
592
626
  `Sela healed it in-memory to let this run pass, but did NOT mutate disk ` +
@@ -606,6 +640,8 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
606
640
  oldSelector: elementSelectorOnly,
607
641
  newSelector: newFullSelector,
608
642
  variablePath: census.variablePath,
643
+ declarationFile,
644
+ declarationLine,
609
645
  testFunctionCount: census.testFunctionCount,
610
646
  affectedFiles: census.affectedFiles,
611
647
  ghostDiff,
@@ -17,6 +17,12 @@ export interface ASTUpdateResult {
17
17
  file: string;
18
18
  line: number;
19
19
  };
20
+ /**
21
+ * Speculative unified diff of the definition-site mutation (before → after),
22
+ * computed in memory. Populated by the cross-file healer so the shared-locator
23
+ * bypass preview can render a root-declaration diff without a disk write.
24
+ */
25
+ unifiedDiff?: string;
20
26
  /** Number of test functions referencing the mutated constant (blast radius). */
21
27
  blastRadius?: number;
22
28
  }
@@ -44,6 +50,13 @@ export interface ComposeHealInput {
44
50
  contextSpecific?: boolean;
45
51
  /** Runtime: selector rot is global across all consumers. */
46
52
  globalCorrect?: boolean;
53
+ /**
54
+ * When true, force MUTATE_IN_PLACE for arg-level diff preview regardless of
55
+ * consumer count. Used by composeHealPreview so shared-variable diffs are
56
+ * computed even when decideArgs would normally return PROMPT_INTERACTIVE.
57
+ * Has no effect on disk: the caller must ensure write:false / DryRunGuard.
58
+ */
59
+ previewMode?: boolean;
47
60
  /** When true, write the result via MutationApplier (with the gate). */
48
61
  apply?: boolean;
49
62
  applyOptions?: ApplyOptions;
@@ -69,6 +82,33 @@ export declare class ASTSourceUpdater {
69
82
  * write it to disk through the type-safety gate.
70
83
  */
71
84
  static composeHeal(input: ComposeHealInput): Promise<ComposeHealResult>;
85
+ /**
86
+ * Speculative, ZERO-WRITE preview of the root-declaration heal.
87
+ *
88
+ * Runs the exact same trace-back + mutation engine `composeHeal` uses, but
89
+ * under a forcibly-suppressed dry-run scope AND with `write:false`, so NO
90
+ * write-head (MutationApplier, InitializerUpdater, CrossFileHealer) can touch
91
+ * disk. Returns the root-declaration unified diff a real heal WOULD have
92
+ * produced — used by the shared-locator bypass gate so its report card shows
93
+ * the elegant declaration-root diff (uniform with HEALED events) instead of a
94
+ * raw selector-string swap.
95
+ *
96
+ * The diff is sourced from the canonical heal pipeline:
97
+ * • same-file paths (local const / same-file POM property) → MutationApplier
98
+ * `outcome.microDiff`,
99
+ * • cross-file imported declarations → `crossFileResult.unifiedDiff`.
100
+ *
101
+ * Returns an empty `ghostDiff` when the engine cannot resolve a root (trace
102
+ * abort / exotic shape); the caller falls back to the legacy selector diff.
103
+ */
104
+ static composeHealPreview(input: ComposeHealInput): Promise<{
105
+ ghostDiff: string;
106
+ definitionSite?: {
107
+ file: string;
108
+ line: number;
109
+ };
110
+ writtenLine?: number;
111
+ }>;
72
112
  /** Drain-loop entry: apply pre-built batches through the write gate. */
73
113
  static applyMutationBatches(batches: FileBatch[], opts?: ApplyOptions): ApplyOutcome[];
74
114
  /** Convert a DecisionEngine result into an anchored MutationApplier batch. */
@@ -140,6 +180,16 @@ export declare class ASTSourceUpdater {
140
180
  private updateObjectProperty;
141
181
  private lineToOffset;
142
182
  resolveFilePath(raw: string): string | null;
183
+ /**
184
+ * ZERO-WRITE preview of the legacy semantic definition-site heal. Reuses the
185
+ * REAL tracer (DefinitionTracer) + write-head (InitializerUpdater) via
186
+ * semanticDispatch with the high-blast BLOCK bypassed, so it computes the
187
+ * root-declaration diff a shared symbolic locator (identifier / property /
188
+ * cross-file) WOULD receive — covering the bypass cases composeHeal returns
189
+ * PROMPT_INTERACTIVE for. MUST run inside DryRunGuard.runSuppressed so
190
+ * InitializerUpdater keeps the mutation in memory and never touches disk.
191
+ */
192
+ previewSemanticHeal(caller: CallerContext, oldSelector: string, newSelector: string): ASTUpdateResult | null;
143
193
  private semanticDispatch;
144
194
  private applyDefinitionSiteHeal;
145
195
  private handleIdentifierArg;
@@ -1 +1 @@
1
- {"version":3,"file":"ASTSourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/ASTSourceUpdater.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ASTSourceUpdater.d.ts","sourceRoot":"","sources":["../../src/services/ASTSourceUpdater.ts"],"names":[],"mappings":"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"}
@@ -1999,7 +1999,9 @@ class ASTSourceUpdater {
1999
1999
  argTargets,
2000
2000
  failingCallSite: failingNode,
2001
2001
  contextSpecific: input.contextSpecific ?? false,
2002
- globalCorrect: input.globalCorrect ?? false,
2002
+ // previewMode forces MUTATE_IN_PLACE regardless of consumer count so
2003
+ // the diff is always computable (no disk write — caller holds the gate).
2004
+ globalCorrect: (input.globalCorrect ?? false) || (input.previewMode ?? false),
2003
2005
  });
2004
2006
  if (argDecision) {
2005
2007
  const batch = ASTSourceUpdater.decisionToBatch(input.filePath, argDecision);
@@ -2042,6 +2044,74 @@ class ASTSourceUpdater {
2042
2044
  }
2043
2045
  return result;
2044
2046
  }
2047
+ /**
2048
+ * Speculative, ZERO-WRITE preview of the root-declaration heal.
2049
+ *
2050
+ * Runs the exact same trace-back + mutation engine `composeHeal` uses, but
2051
+ * under a forcibly-suppressed dry-run scope AND with `write:false`, so NO
2052
+ * write-head (MutationApplier, InitializerUpdater, CrossFileHealer) can touch
2053
+ * disk. Returns the root-declaration unified diff a real heal WOULD have
2054
+ * produced — used by the shared-locator bypass gate so its report card shows
2055
+ * the elegant declaration-root diff (uniform with HEALED events) instead of a
2056
+ * raw selector-string swap.
2057
+ *
2058
+ * The diff is sourced from the canonical heal pipeline:
2059
+ * • same-file paths (local const / same-file POM property) → MutationApplier
2060
+ * `outcome.microDiff`,
2061
+ * • cross-file imported declarations → `crossFileResult.unifiedDiff`.
2062
+ *
2063
+ * Returns an empty `ghostDiff` when the engine cannot resolve a root (trace
2064
+ * abort / exotic shape); the caller falls back to the legacy selector diff.
2065
+ */
2066
+ static async composeHealPreview(input) {
2067
+ return DryRunGuard_1.DryRunGuard.runSuppressed(async () => {
2068
+ // 1) Canonical compose pipeline — handles option-object args (getByRole
2069
+ // name), inline string args, and cross-file imports it can resolve.
2070
+ const composed = await ASTSourceUpdater.composeHeal({
2071
+ ...input,
2072
+ apply: true,
2073
+ // Force MUTATE_IN_PLACE for multi-consumer symbolic args so the root-
2074
+ // declaration diff is always computed (shared-locator bypass preview).
2075
+ previewMode: true,
2076
+ applyOptions: {
2077
+ ...(input.applyOptions ?? {}),
2078
+ write: false,
2079
+ respectDryRun: true,
2080
+ },
2081
+ });
2082
+ if (composed.kind === "cross-file" && composed.crossFileResult?.unifiedDiff) {
2083
+ const cross = composed.crossFileResult;
2084
+ return {
2085
+ ghostDiff: cross.unifiedDiff ?? "",
2086
+ definitionSite: cross.definitionSite,
2087
+ writtenLine: cross.definitionSite?.line ?? composed.writtenLine,
2088
+ };
2089
+ }
2090
+ if (composed.outcome?.microDiff) {
2091
+ return {
2092
+ ghostDiff: composed.outcome.microDiff,
2093
+ writtenLine: composed.writtenLine,
2094
+ };
2095
+ }
2096
+ // 2) Fallback — gate-free legacy semantic preview. composeHeal returns
2097
+ // PROMPT_INTERACTIVE (no diff) for shared symbolic locators; this
2098
+ // reuses the real tracer + write-head to compute the root diff anyway.
2099
+ try {
2100
+ const semantic = new ASTSourceUpdater().previewSemanticHeal({ filePath: input.filePath, line: input.line }, input.oldSelector ?? "", input.newSelector ?? "");
2101
+ if (semantic?.unifiedDiff) {
2102
+ return {
2103
+ ghostDiff: semantic.unifiedDiff,
2104
+ definitionSite: semantic.definitionSite,
2105
+ writtenLine: semantic.definitionSite?.line,
2106
+ };
2107
+ }
2108
+ }
2109
+ catch (err) {
2110
+ logger_1.logger.debug(`previewSemanticHeal fallback failed: ${err?.message ?? err}`);
2111
+ }
2112
+ return { ghostDiff: "" };
2113
+ });
2114
+ }
2045
2115
  /** Drain-loop entry: apply pre-built batches through the write gate. */
2046
2116
  static applyMutationBatches(batches, opts = {}) {
2047
2117
  return MutationApplier_1.MutationApplier.applyBatches(batches, opts);
@@ -3482,7 +3552,27 @@ class ASTSourceUpdater {
3482
3552
  // ═══════════════════════════════════════════════════════════════════
3483
3553
  // T-10 / T-11: Semantic Dispatch Gate + handlers
3484
3554
  // ═══════════════════════════════════════════════════════════════════
3485
- semanticDispatch(sourceFile, caller, oldSelector, newSelector) {
3555
+ /**
3556
+ * ZERO-WRITE preview of the legacy semantic definition-site heal. Reuses the
3557
+ * REAL tracer (DefinitionTracer) + write-head (InitializerUpdater) via
3558
+ * semanticDispatch with the high-blast BLOCK bypassed, so it computes the
3559
+ * root-declaration diff a shared symbolic locator (identifier / property /
3560
+ * cross-file) WOULD receive — covering the bypass cases composeHeal returns
3561
+ * PROMPT_INTERACTIVE for. MUST run inside DryRunGuard.runSuppressed so
3562
+ * InitializerUpdater keeps the mutation in memory and never touches disk.
3563
+ */
3564
+ previewSemanticHeal(caller, oldSelector, newSelector) {
3565
+ const filePath = this.resolveFilePath(caller.filePath);
3566
+ if (!filePath || caller.line <= 0)
3567
+ return null;
3568
+ let sourceFile = this.project.getSourceFile(filePath);
3569
+ if (sourceFile)
3570
+ sourceFile.refreshFromFileSystemSync();
3571
+ else
3572
+ sourceFile = this.project.addSourceFileAtPath(filePath);
3573
+ return this.semanticDispatch(sourceFile, { filePath, line: caller.line }, oldSelector, newSelector, true);
3574
+ }
3575
+ semanticDispatch(sourceFile, caller, oldSelector, newSelector, preview = false) {
3486
3576
  try {
3487
3577
  // Expand window: the failure site (caller.line) is often .click()/.fill()
3488
3578
  // AFTER the locator assignment. Search up to 5 lines back so we catch
@@ -3493,14 +3583,57 @@ class ASTSourceUpdater {
3493
3583
  if (!analysis)
3494
3584
  continue;
3495
3585
  const { shape, node } = analysis;
3496
- if (shape === "STRING_LITERAL" || shape === "COMPLEX")
3586
+ if (shape === "COMPLEX")
3497
3587
  continue;
3588
+ // Semantic methods (getByRole, getByText, etc.) pass a role/text as
3589
+ // arg0 (always a STRING_LITERAL) and text-matching options in arg1.
3590
+ // e.g. getByRole("button", { name: updateSelector }) — classify()
3591
+ // returns STRING_LITERAL for "button" and we'd normally skip, but
3592
+ // updateSelector in { name: updateSelector } is the real target.
3593
+ if (shape === "STRING_LITERAL") {
3594
+ const callExpr = call.getExpression();
3595
+ const method = ts_morph_1.Node.isPropertyAccessExpression(callExpr)
3596
+ ? callExpr.getName()
3597
+ : "";
3598
+ if (SEMANTIC_METHODS.has(method)) {
3599
+ const optsArg = call.getArguments()[1];
3600
+ if (optsArg && ts_morph_1.Node.isObjectLiteralExpression(optsArg)) {
3601
+ for (const optProp of optsArg.getProperties()) {
3602
+ if (!ts_morph_1.Node.isPropertyAssignment(optProp))
3603
+ continue;
3604
+ const val = optProp.getInitializer();
3605
+ if (!val)
3606
+ continue;
3607
+ const valShape = ArgumentTypeAnalyzer_1.ArgumentTypeAnalyzer.classifyNode(val);
3608
+ let optResult = null;
3609
+ if (valShape === "IDENTIFIER") {
3610
+ optResult = this.handleIdentifierArg(val, sourceFile, caller, newSelector, oldSelector, preview);
3611
+ }
3612
+ else if (valShape === "PROPERTY_ACCESS") {
3613
+ optResult = this.handlePropertyAccessArg(val, sourceFile, caller, newSelector, preview);
3614
+ }
3615
+ if (optResult !== null)
3616
+ return optResult;
3617
+ // Symbolic options arg that couldn't be traced — hard-block so
3618
+ // the chain is not rewritten inline (preserves developer arch).
3619
+ if (valShape === "IDENTIFIER" || valShape === "PROPERTY_ACCESS") {
3620
+ return {
3621
+ success: false,
3622
+ reason: `semantic guard: options identifier "${val.getText()}" could not be traced`,
3623
+ strategy: "semantic-guard",
3624
+ };
3625
+ }
3626
+ }
3627
+ }
3628
+ }
3629
+ continue;
3630
+ }
3498
3631
  let result = null;
3499
3632
  if (shape === "IDENTIFIER") {
3500
- result = this.handleIdentifierArg(node, sourceFile, caller, newSelector, oldSelector);
3633
+ result = this.handleIdentifierArg(node, sourceFile, caller, newSelector, oldSelector, preview);
3501
3634
  }
3502
3635
  else if (shape === "PROPERTY_ACCESS") {
3503
- result = this.handlePropertyAccessArg(node, sourceFile, caller, newSelector);
3636
+ result = this.handlePropertyAccessArg(node, sourceFile, caller, newSelector, preview);
3504
3637
  }
3505
3638
  else if (shape === "TEMPLATE_LITERAL") {
3506
3639
  result = this.handleTemplateLiteralArg(node, sourceFile, caller, oldSelector, newSelector);
@@ -3550,7 +3683,7 @@ class ASTSourceUpdater {
3550
3683
  // intact — while surfacing the cleaner semantic method form (getByRole) as
3551
3684
  // a suggested upgrade in the advisory/report.
3552
3685
  // ═══════════════════════════════════════════════════════════════════
3553
- applyDefinitionSiteHeal(targetNode, targetFile, newSelector, strategy, blastRadius) {
3686
+ applyDefinitionSiteHeal(targetNode, targetFile, newSelector, strategy, blastRadius, preview = false) {
3554
3687
  const wasInternal = (0, SelectorSanitizer_1.isInternalEngineSelector)(newSelector);
3555
3688
  let writeValue = newSelector;
3556
3689
  if (wasInternal) {
@@ -3568,7 +3701,9 @@ class ASTSourceUpdater {
3568
3701
  writeValue = publicStr;
3569
3702
  logger_1.logger.debug(`Method-Shift fallback: internal selector → public string "${writeValue}"`);
3570
3703
  }
3571
- const result = InitializerUpdater_1.InitializerUpdater.apply(targetNode, targetFile, writeValue);
3704
+ const result = InitializerUpdater_1.InitializerUpdater.apply(targetNode, targetFile, writeValue, {
3705
+ computeDiff: preview,
3706
+ });
3572
3707
  if (!result)
3573
3708
  return null;
3574
3709
  if (!this.validateFileSyntax(targetFile)) {
@@ -3601,10 +3736,11 @@ class ASTSourceUpdater {
3601
3736
  file: targetFile.getFilePath(),
3602
3737
  line: result.lineUpdated,
3603
3738
  },
3739
+ unifiedDiff: result.unifiedDiff,
3604
3740
  blastRadius,
3605
3741
  };
3606
3742
  }
3607
- handleIdentifierArg(node, sourceFile, caller, newSelector, oldSelector = "") {
3743
+ handleIdentifierArg(node, sourceFile, caller, newSelector, oldSelector = "", preview = false) {
3608
3744
  const traceResult = DefinitionTracer_1.DefinitionTracer.traceIdentifier(node, sourceFile, caller.line);
3609
3745
  if (traceResult.found) {
3610
3746
  const { targetNode, targetFile, declarationNode } = traceResult;
@@ -3612,7 +3748,10 @@ class ASTSourceUpdater {
3612
3748
  const blast = BlastRadiusAnalyzer_1.BlastRadiusAnalyzer.analyze(blastNode, sourceFile, this.project);
3613
3749
  logger_1.logger.debug(`BlastRadius IDENTIFIER: risk=${blast.risk} ` +
3614
3750
  `(${blast.testFunctionCount} tests, ${blast.affectedFiles.length} files)`);
3615
- if (blast.risk === "high") {
3751
+ // Preview mode (shared-locator bypass ghost diff) deliberately bypasses
3752
+ // the high-blast BLOCK: it never writes disk, it only computes what the
3753
+ // root-declaration mutation WOULD look like. The real heal still blocks.
3754
+ if (blast.risk === "high" && !preview) {
3616
3755
  this.advisoryBuffer.push({
3617
3756
  code: HealingAdvisory_1.AdvisoryCode.BLAST_RADIUS_BLOCKED,
3618
3757
  message: `Mutation blocked - ${blast.testFunctionCount} tests reference this constant.`,
@@ -3635,7 +3774,7 @@ class ASTSourceUpdater {
3635
3774
  suggestedAction: "Run the full test suite to confirm all references still pass.",
3636
3775
  });
3637
3776
  }
3638
- const healResult = this.applyDefinitionSiteHeal(targetNode, targetFile, newSelector, "semantic-identifier", blast.testFunctionCount);
3777
+ const healResult = this.applyDefinitionSiteHeal(targetNode, targetFile, newSelector, "semantic-identifier", blast.testFunctionCount, preview);
3639
3778
  if (!healResult && oldSelector) {
3640
3779
  // targetNode was not a string literal (e.g. CallExpression from an
3641
3780
  // indirect reference like switch/case POM). Search targetFile for the
@@ -3693,7 +3832,7 @@ class ASTSourceUpdater {
3693
3832
  blastRadius: 1,
3694
3833
  };
3695
3834
  }
3696
- handlePropertyAccessArg(node, sourceFile, caller, newSelector) {
3835
+ handlePropertyAccessArg(node, sourceFile, caller, newSelector, preview = false) {
3697
3836
  const traceResult = DefinitionTracer_1.DefinitionTracer.tracePropertyAccess(node, sourceFile, caller.line);
3698
3837
  if (traceResult.found) {
3699
3838
  const { targetNode, targetFile, declarationNode } = traceResult;
@@ -3701,7 +3840,7 @@ class ASTSourceUpdater {
3701
3840
  const blast = BlastRadiusAnalyzer_1.BlastRadiusAnalyzer.analyze(blastNode, sourceFile, this.project);
3702
3841
  logger_1.logger.debug(`BlastRadius PROPERTY_ACCESS: risk=${blast.risk} ` +
3703
3842
  `(${blast.testFunctionCount} tests, ${blast.affectedFiles.length} files)`);
3704
- if (blast.risk === "high") {
3843
+ if (blast.risk === "high" && !preview) {
3705
3844
  this.advisoryBuffer.push({
3706
3845
  code: HealingAdvisory_1.AdvisoryCode.BLAST_RADIUS_BLOCKED,
3707
3846
  message: `Mutation blocked - ${blast.testFunctionCount} tests reference this property.`,
@@ -3724,7 +3863,7 @@ class ASTSourceUpdater {
3724
3863
  suggestedAction: "Run the full test suite to confirm all references still pass.",
3725
3864
  });
3726
3865
  }
3727
- return this.applyDefinitionSiteHeal(targetNode, targetFile, newSelector, "semantic-property-access", blast.testFunctionCount);
3866
+ return this.applyDefinitionSiteHeal(targetNode, targetFile, newSelector, "semantic-property-access", blast.testFunctionCount, preview);
3728
3867
  }
3729
3868
  if (!traceResult.found && traceResult.crossFile) {
3730
3869
  const xResult = CrossFileHealer_1.CrossFileHealer.heal(traceResult.modulePath, traceResult.symbolName, newSelector, caller.filePath, this.project);
@@ -1 +1 @@
1
- {"version":3,"file":"CrossFileHealer.d.ts","sourceRoot":"","sources":["../../src/services/CrossFileHealer.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,OAAO,EAMR,MAAM,UAAU,CAAC;AAGlB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAmB7D,qBAAa,eAAe;IAC1B,MAAM,CAAC,IAAI,CACT,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,OAAO,EAChB,KAAK,SAAI,GACR,eAAe;IAuFlB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,eAAe,CACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,OAAO,GACf,eAAe;CAkEnB;AAMD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAQf"}
1
+ {"version":3,"file":"CrossFileHealer.d.ts","sourceRoot":"","sources":["../../src/services/CrossFileHealer.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,OAAO,EAMR,MAAM,UAAU,CAAC;AAGlB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAuC7D,qBAAa,eAAe;IAC1B,MAAM,CAAC,IAAI,CACT,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,OAAO,EAChB,KAAK,SAAI,GACR,eAAe;IA6FlB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,eAAe,CACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,OAAO,GACf,eAAe;CAoEnB;AAMD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAQf"}
@@ -40,7 +40,20 @@ const fs = __importStar(require("fs"));
40
40
  const ts_morph_1 = require("ts-morph");
41
41
  const DefinitionTracer_js_1 = require("./DefinitionTracer.js");
42
42
  const InitializerUpdater_js_1 = require("./InitializerUpdater.js");
43
+ const IsolatedDiff_1 = require("../utils/IsolatedDiff");
43
44
  const logger_1 = require("../utils/logger");
45
+ /**
46
+ * Compute the in-memory unified diff for a ts-morph source file whose AST was
47
+ * just mutated. `before` is the pre-mutation text; the live file text is the
48
+ * `after`. Returns undefined when nothing changed. Never touches disk.
49
+ */
50
+ function captureDefinitionDiff(before, externalSf, externalPath) {
51
+ return ((0, IsolatedDiff_1.generateUnifiedDiff)(before, externalSf.getFullText(), {
52
+ filePath: path.relative(process.cwd(), externalPath),
53
+ context: 3,
54
+ normalizeEol: true,
55
+ }) || undefined);
56
+ }
44
57
  // ═══════════════════════════════════════════════════════════════════
45
58
  // CrossFileHealer (T-9)
46
59
  //
@@ -102,6 +115,7 @@ class CrossFileHealer {
102
115
  strategy: "semantic-cross-file",
103
116
  };
104
117
  }
118
+ const before = traceResult.targetFile.getFullText();
105
119
  const result = InitializerUpdater_js_1.InitializerUpdater.apply(traceResult.targetNode, traceResult.targetFile, newValue);
106
120
  if (!result) {
107
121
  return {
@@ -119,6 +133,7 @@ class CrossFileHealer {
119
133
  lineUpdated: result.lineUpdated,
120
134
  healedLocatorString: newValue,
121
135
  definitionSite: { file: externalPath, line: result.lineUpdated + 1 },
136
+ unifiedDiff: captureDefinitionDiff(before, traceResult.targetFile, externalPath),
122
137
  };
123
138
  }
124
139
  /**
@@ -174,6 +189,7 @@ class CrossFileHealer {
174
189
  strategy: "semantic-cross-file",
175
190
  };
176
191
  }
192
+ const before = externalSf.getFullText();
177
193
  const result = InitializerUpdater_js_1.InitializerUpdater.apply(targetNode, externalSf, newValue);
178
194
  if (!result) {
179
195
  return {
@@ -191,6 +207,7 @@ class CrossFileHealer {
191
207
  lineUpdated: result.lineUpdated,
192
208
  healedLocatorString: newValue,
193
209
  definitionSite: { file: externalPath, line: result.lineUpdated + 1 },
210
+ unifiedDiff: captureDefinitionDiff(before, externalSf, externalPath),
194
211
  };
195
212
  }
196
213
  }
@@ -113,11 +113,22 @@ export interface BypassedEvent extends HealEventBase {
113
113
  newSelector: string;
114
114
  /** "relative/path.ts:LINE" — the shared declaration that was left untouched. */
115
115
  variablePath: string;
116
+ /**
117
+ * Origin locus of the shared declaration the ghost diff targets — the
118
+ * variable/property root, NOT the failing call-site (which stays on
119
+ * sourceFile/sourceLine for the Job-2 regression replay). Drives the HTML
120
+ * card's "open declaration" highlight.
121
+ */
122
+ declarationFile?: string;
123
+ declarationLine?: number;
116
124
  /** Distinct test/it blocks that reference the shared declaration. */
117
125
  testFunctionCount: number;
118
126
  /** Files that reference the shared declaration. */
119
127
  affectedFiles: string[];
120
- /** Speculative unified diff of what Sela WOULD have written (never saved). */
128
+ /**
129
+ * Speculative ROOT-DECLARATION unified diff of what Sela WOULD have written
130
+ * (never saved) — uniform in shape with a HEALED event's diff.
131
+ */
121
132
  ghostDiff: string;
122
133
  /** Human-readable warning surfaced across all report channels. */
123
134
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"HealReportService.d.ts","sourceRoot":"","sources":["../../src/services/HealReportService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"HealReportService.d.ts","sourceRoot":"","sources":["../../src/services/HealReportService.ts"],"names":[],"mappings":"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"}
@@ -1048,7 +1048,7 @@ const REPORT_JS = [
1048
1048
  " +'<div class=\"diff-line dl-add\"><span class=\"gutter\">+</span><span class=\"ln\">'+(ev.newLineNumber||'')+'</span><span class=\"code\">'+esc(ev.newCodeLine||'')+'</span></div>';",
1049
1049
  " }",
1050
1050
  " if(isBypass){",
1051
- " return'<div class=\"diff-block diff-ghost\"><div class=\"diff-bar\"><span>'+esc(ev.variablePath||ev.sourceFile)+'</span><span class=\"sep\">\xb7</span><span class=\"ghost-tag\">SPECULATIVE — NOT SAVED TO DISK</span></div><div>'+body+'</div></div>';",
1051
+ " return'<div class=\"diff-block diff-ghost\"><div class=\"diff-bar\"><span>'+esc((ev.declarationFile?ev.declarationFile+(ev.declarationLine?':'+ev.declarationLine:''):'')||ev.variablePath||ev.sourceFile)+'</span><span class=\"sep\">\xb7</span><span class=\"ghost-tag\">[SPECULATIVE ROOT FIX PENDING REGRESSION VALIDATION] · NOT SAVED TO DISK</span></div><div>'+body+'</div></div>';",
1052
1052
  " }",
1053
1053
  " return'<div class=\"diff-block\"><div class=\"diff-bar\"><span>'+esc(ev.sourceFile)+'</span><span class=\"sep\">\xb7</span><span>line '+ev.newLineNumber+'</span>'+(ev.diffStrategy?'<span class=\"sep\">\xb7</span><span>'+esc(ev.diffStrategy)+'</span>':'')+'<span class=\"sep\">\xb7</span><span>'+(hasDiff?'git diff':'fallback')+'</span></div><div>'+body+'</div></div>';",
1054
1054
  "}",
@@ -2,6 +2,17 @@ import { Node, SourceFile } from "ts-morph";
2
2
  export interface InitializerResult {
3
3
  lineUpdated: number;
4
4
  healedLocatorString: string;
5
+ /**
6
+ * In-memory unified diff (before → after) of the mutated source file.
7
+ * Only populated when `apply` is called with `{ computeDiff: true }` —
8
+ * used by the shared-locator bypass preview to render a root-declaration
9
+ * diff with zero disk writes.
10
+ */
11
+ unifiedDiff?: string;
12
+ }
13
+ export interface InitializerApplyOptions {
14
+ /** Compute and return the in-memory before→after unified diff. */
15
+ computeDiff?: boolean;
5
16
  }
6
17
  export declare class InitializerUpdater {
7
18
  /**
@@ -11,6 +22,6 @@ export declare class InitializerUpdater {
11
22
  * Returns null if the node type is not directly mutable or if the
12
23
  * mutation throws (caller should fall through to existing strategies).
13
24
  */
14
- static apply(valueNode: Node, sourceFile: SourceFile, newValue: string): InitializerResult | null;
25
+ static apply(valueNode: Node, sourceFile: SourceFile, newValue: string, opts?: InitializerApplyOptions): InitializerResult | null;
15
26
  }
16
27
  //# sourceMappingURL=InitializerUpdater.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InitializerUpdater.d.ts","sourceRoot":"","sources":["../../src/services/InitializerUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAiB,MAAM,UAAU,CAAC;AAiB3D,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,kBAAkB;IAC7B;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,IAAI,EACf,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,GACf,iBAAiB,GAAG,IAAI;CAwD5B"}
1
+ {"version":3,"file":"InitializerUpdater.d.ts","sourceRoot":"","sources":["../../src/services/InitializerUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAiB,MAAM,UAAU,CAAC;AAmB3D,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,kBAAkB;IAC7B;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,IAAI,EACf,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,uBAA4B,GACjC,iBAAiB,GAAG,IAAI;CAiE5B"}
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.InitializerUpdater = void 0;
4
37
  const ts_morph_1 = require("ts-morph");
@@ -7,7 +40,9 @@ const DryRunGuard_1 = require("../config/DryRunGuard");
7
40
  const PathScopeGuard_1 = require("../config/PathScopeGuard");
8
41
  const WorkspaceSnapshotService_1 = require("./WorkspaceSnapshotService");
9
42
  const SelectorSanitizer_1 = require("./SelectorSanitizer");
43
+ const IsolatedDiff_1 = require("../utils/IsolatedDiff");
10
44
  const logger_1 = require("../utils/logger");
45
+ const path = __importStar(require("path"));
11
46
  class InitializerUpdater {
12
47
  /**
13
48
  * Mutate a StringLiteral or NoSubstitutionTemplateLiteral node to
@@ -16,7 +51,7 @@ class InitializerUpdater {
16
51
  * Returns null if the node type is not directly mutable or if the
17
52
  * mutation throws (caller should fall through to existing strategies).
18
53
  */
19
- static apply(valueNode, sourceFile, newValue) {
54
+ static apply(valueNode, sourceFile, newValue, opts = {}) {
20
55
  // ABSOLUTE GUARD: never serialise a Playwright internal engine selector
21
56
  // into a string-literal definition. `.locator()` strings cannot express
22
57
  // a semantic locator (getByRole/…), so writing `internal:role=…` here is
@@ -32,6 +67,7 @@ class InitializerUpdater {
32
67
  return null;
33
68
  }
34
69
  try {
70
+ const before = opts.computeDiff ? sourceFile.getFullText() : "";
35
71
  if (ts_morph_1.Node.isStringLiteral(valueNode)) {
36
72
  valueNode.setLiteralValue(newValue);
37
73
  }
@@ -41,6 +77,13 @@ class InitializerUpdater {
41
77
  else {
42
78
  return null;
43
79
  }
80
+ const unifiedDiff = opts.computeDiff
81
+ ? (0, IsolatedDiff_1.generateUnifiedDiff)(before, sourceFile.getFullText(), {
82
+ filePath: path.relative(process.cwd(), sourceFile.getFilePath()),
83
+ context: 3,
84
+ normalizeEol: true,
85
+ }) || undefined
86
+ : undefined;
44
87
  // Centralised write gate - mirrors ASTSourceUpdater._persistChanges.
45
88
  // InitializerUpdater is the canonical write-head for definition-site
46
89
  // mutations (SemanticDispatch → tracer-resolved identifier / property
@@ -62,6 +105,7 @@ class InitializerUpdater {
62
105
  return {
63
106
  lineUpdated: valueNode.getStartLineNumber() - 1,
64
107
  healedLocatorString: newValue,
108
+ unifiedDiff,
65
109
  };
66
110
  }
67
111
  catch (e) {
@@ -14,6 +14,14 @@ export interface RegressionManifestRecord {
14
14
  affectedFiles: string[];
15
15
  /** Originating test title (provenance only). */
16
16
  testTitle: string;
17
+ /**
18
+ * Speculative ROOT-DECLARATION unified diff Sela WOULD have written (never
19
+ * saved). Carried for report/audit parity; Job 2 matches on the call-site
20
+ * fields above and never consumes this. Optional — absent on legacy manifests.
21
+ */
22
+ rootDiff?: string;
23
+ /** Origin locus of the shared declaration the rootDiff targets (provenance). */
24
+ declarationFile?: string;
17
25
  }
18
26
  export interface RegressionManifest {
19
27
  generatedAt: string;
@@ -1 +1 @@
1
- {"version":3,"file":"RegressionManifestService.d.ts","sourceRoot":"","sources":["../../src/services/RegressionManifestService.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AAExE,oEAAoE;AACpE,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,wBAAwB,EAAE,CAAC;CACrC;AAMD,qBAAa,yBAAyB;IACpC,+DAA+D;IAC/D,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,wBAAwB,EAAE;IAWxE;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAClB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,wBAAwB,EAAE,GAClC,MAAM,GAAG,IAAI;IAYhB;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB;IAkBzD,OAAO,CAAC,MAAM,CAAC,QAAQ;CAiDxB;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;gBAEzC,QAAQ,EAAE,kBAAkB;IAIxC,yEAAyE;IACzE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB;IAMrD;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAY3E"}
1
+ {"version":3,"file":"RegressionManifestService.d.ts","sourceRoot":"","sources":["../../src/services/RegressionManifestService.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AAExE,oEAAoE;AACpE,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,wBAAwB,EAAE,CAAC;CACrC;AAMD,qBAAa,yBAAyB;IACpC,+DAA+D;IAC/D,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,wBAAwB,EAAE;IAexE;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAClB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,wBAAwB,EAAE,GAClC,MAAM,GAAG,IAAI;IAYhB;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB;IAkBzD,OAAO,CAAC,MAAM,CAAC,QAAQ;CAqDxB;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;gBAEzC,QAAQ,EAAE,kBAAkB;IAIxC,yEAAyE;IACzE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB;IAMrD;;;;;;OAMG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAY3E"}
@@ -61,6 +61,10 @@ class RegressionManifestService {
61
61
  healedSelector: ev.newSelector,
62
62
  affectedFiles: (ev.affectedFiles ?? []).map(normalizePath),
63
63
  testTitle: ev.testTitle ?? "",
64
+ ...(ev.ghostDiff ? { rootDiff: ev.ghostDiff } : {}),
65
+ ...(ev.declarationFile
66
+ ? { declarationFile: normalizePath(ev.declarationFile) }
67
+ : {}),
64
68
  }));
65
69
  }
66
70
  /**
@@ -129,6 +133,10 @@ class RegressionManifestService {
129
133
  ? rec.affectedFiles.filter((x) => typeof x === "string")
130
134
  : [],
131
135
  testTitle: typeof rec.testTitle === "string" ? rec.testTitle : "",
136
+ ...(typeof rec.rootDiff === "string" ? { rootDiff: rec.rootDiff } : {}),
137
+ ...(typeof rec.declarationFile === "string"
138
+ ? { declarationFile: rec.declarationFile }
139
+ : {}),
132
140
  };
133
141
  });
134
142
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sela-core",
3
- "version": "0.1.0-alpha.36",
3
+ "version": "0.1.0-alpha.37",
4
4
  "description": "AI self-healing Playwright wrapper - drop-in replacement for @playwright/test",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",