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.
- package/README.md +27 -17
- package/dist/cli/ErrorHandler.d.ts +1 -1
- package/dist/cli/ErrorHandler.js +14 -14
- package/dist/cli/commands/bulk.d.ts +1 -1
- package/dist/cli/commands/bulk.d.ts.map +1 -1
- package/dist/cli/commands/bulk.js +51 -33
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +26 -18
- package/dist/cli/commands/merge.d.ts +13 -0
- package/dist/cli/commands/merge.d.ts.map +1 -0
- package/dist/cli/commands/merge.js +119 -0
- package/dist/cli/commands/showReport.d.ts +1 -1
- package/dist/cli/commands/showReport.d.ts.map +1 -1
- package/dist/cli/commands/showReport.js +12 -10
- package/dist/cli/commands/status.d.ts +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +8 -8
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/commands/sync.js +38 -30
- package/dist/cli/index.js +12 -9
- package/dist/cli/ui/DnaTable.d.ts +1 -1
- package/dist/cli/ui/DnaTable.d.ts.map +1 -1
- package/dist/cli/ui/DnaTable.js +23 -16
- package/dist/cli/ui/RefactorWizard.d.ts +3 -3
- package/dist/cli/ui/RefactorWizard.d.ts.map +1 -1
- package/dist/cli/ui/RefactorWizard.js +108 -82
- package/dist/config/ConfigLoader.d.ts +2 -2
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +15 -15
- package/dist/config/DryRunGuard.d.ts +1 -1
- package/dist/config/DryRunGuard.js +7 -7
- package/dist/config/SelaConfig.d.ts +13 -17
- package/dist/config/SelaConfig.d.ts.map +1 -1
- package/dist/config/SelaConfig.js +32 -26
- package/dist/engine/HealingRegistry.d.ts +1 -1
- package/dist/engine/HealingRegistry.js +3 -3
- package/dist/engine/SelaEngine.d.ts +1 -1
- package/dist/engine/SelaEngine.d.ts.map +1 -1
- package/dist/engine/SelaEngine.js +117 -51
- package/dist/errors/SelaError.d.ts +8 -1
- package/dist/errors/SelaError.d.ts.map +1 -1
- package/dist/errors/SelaError.js +14 -7
- package/dist/fixtures/expectProxy.d.ts +2 -2
- package/dist/fixtures/expectProxy.js +16 -16
- package/dist/fixtures/index.d.ts +18 -2
- package/dist/fixtures/index.d.ts.map +1 -1
- package/dist/fixtures/index.js +47 -27
- package/dist/fixtures/moduleExpect.js +7 -7
- package/dist/fixtures/proxyTag.d.ts +1 -1
- package/dist/fixtures/proxyTag.js +4 -4
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/reporter/SelaReporter.d.ts +45 -12
- package/dist/reporter/SelaReporter.d.ts.map +1 -1
- package/dist/reporter/SelaReporter.js +139 -39
- package/dist/services/ASTSourceUpdater.d.ts +48 -3
- package/dist/services/ASTSourceUpdater.d.ts.map +1 -1
- package/dist/services/ASTSourceUpdater.js +283 -105
- package/dist/services/AnchorResolver.d.ts +157 -0
- package/dist/services/AnchorResolver.d.ts.map +1 -0
- package/dist/services/AnchorResolver.js +289 -0
- package/dist/services/ArgumentTypeAnalyzer.js +7 -7
- package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -1
- package/dist/services/BlastRadiusAnalyzer.js +5 -2
- package/dist/services/ChainValidator.js +22 -22
- package/dist/services/CrossFileHealer.js +7 -7
- package/dist/services/DecisionEngine.d.ts +51 -0
- package/dist/services/DecisionEngine.d.ts.map +1 -0
- package/dist/services/DecisionEngine.js +260 -0
- package/dist/services/DefinitionTracer.d.ts +1 -1
- package/dist/services/DefinitionTracer.d.ts.map +1 -1
- package/dist/services/DefinitionTracer.js +28 -13
- package/dist/services/DnaEditorService.d.ts +2 -2
- package/dist/services/DnaEditorService.d.ts.map +1 -1
- package/dist/services/DnaEditorService.js +81 -62
- package/dist/services/DnaIndexService.d.ts +1 -1
- package/dist/services/DnaIndexService.d.ts.map +1 -1
- package/dist/services/DnaIndexService.js +14 -14
- package/dist/services/HealReportService.d.ts +31 -55
- package/dist/services/HealReportService.d.ts.map +1 -1
- package/dist/services/HealReportService.js +864 -1240
- package/dist/services/HealingAdvisory.d.ts +9 -1
- package/dist/services/HealingAdvisory.d.ts.map +1 -1
- package/dist/services/HealingAdvisory.js +9 -1
- package/dist/services/HealingCacheService.d.ts +8 -8
- package/dist/services/HealingCacheService.d.ts.map +1 -1
- package/dist/services/HealingCacheService.js +24 -24
- package/dist/services/HealthReportService.d.ts +1 -1
- package/dist/services/HealthReportService.d.ts.map +1 -1
- package/dist/services/HealthReportService.js +25 -25
- package/dist/services/InitializerUpdater.d.ts.map +1 -1
- package/dist/services/InitializerUpdater.js +12 -2
- package/dist/services/IntentAuditor.d.ts.map +1 -1
- package/dist/services/IntentAuditor.js +32 -21
- package/dist/services/InteractiveReview.d.ts +8 -17
- package/dist/services/InteractiveReview.d.ts.map +1 -1
- package/dist/services/InteractiveReview.js +34 -124
- package/dist/services/LLMService.d.ts +1 -1
- package/dist/services/LLMService.js +16 -16
- package/dist/services/MutationApplier.d.ts +55 -0
- package/dist/services/MutationApplier.d.ts.map +1 -0
- package/dist/services/MutationApplier.js +322 -0
- package/dist/services/PRAutomationService.d.ts +2 -2
- package/dist/services/PRAutomationService.d.ts.map +1 -1
- package/dist/services/PRAutomationService.js +43 -39
- package/dist/services/PendingPromptLedger.d.ts +9 -2
- package/dist/services/PendingPromptLedger.d.ts.map +1 -1
- package/dist/services/PendingPromptLedger.js +31 -6
- package/dist/services/ReportGenerator.d.ts +116 -30
- package/dist/services/ReportGenerator.d.ts.map +1 -1
- package/dist/services/ReportGenerator.js +149 -62
- package/dist/services/ReportMergeService.d.ts +95 -0
- package/dist/services/ReportMergeService.d.ts.map +1 -0
- package/dist/services/ReportMergeService.js +0 -0
- package/dist/services/SafetyGuard.d.ts +4 -7
- package/dist/services/SafetyGuard.d.ts.map +1 -1
- package/dist/services/SafetyGuard.js +29 -106
- package/dist/services/SelectorSanitizer.d.ts +52 -0
- package/dist/services/SelectorSanitizer.d.ts.map +1 -0
- package/dist/services/SelectorSanitizer.js +318 -0
- package/dist/services/SnapshotService.js +6 -6
- package/dist/services/SourceLinkService.d.ts +2 -2
- package/dist/services/SourceLinkService.d.ts.map +1 -1
- package/dist/services/SourceLinkService.js +31 -22
- package/dist/services/SourceUpdater.d.ts +1 -1
- package/dist/services/SourceUpdater.d.ts.map +1 -1
- package/dist/services/SourceUpdater.js +44 -26
- package/dist/services/TemplateDiffService.d.ts.map +1 -1
- package/dist/services/TemplateDiffService.js +18 -15
- package/dist/services/TraceBackEngine.d.ts +67 -0
- package/dist/services/TraceBackEngine.d.ts.map +1 -0
- package/dist/services/TraceBackEngine.js +672 -0
- package/dist/services/WorkspaceSnapshotService.d.ts +6 -6
- package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -1
- package/dist/services/WorkspaceSnapshotService.js +10 -12
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/DOMUtils.d.ts +18 -2
- package/dist/utils/DOMUtils.d.ts.map +1 -1
- package/dist/utils/DOMUtils.js +335 -49
- package/dist/utils/IsolatedDiff.d.ts +2 -2
- package/dist/utils/IsolatedDiff.d.ts.map +1 -1
- package/dist/utils/IsolatedDiff.js +13 -10
- package/package.json +2 -2
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
import type { PendingPromptEntry } from "./PendingPromptLedger";
|
|
2
|
-
export interface
|
|
2
|
+
export interface PrintReviewDeps {
|
|
3
3
|
entries: PendingPromptEntry[];
|
|
4
|
-
/** Override the
|
|
5
|
-
prompt?: (question: string) => Promise<string>;
|
|
6
|
-
/** Override the console sink — tests capture output for assertions. */
|
|
4
|
+
/** Override the console sink - tests capture output for assertions. */
|
|
7
5
|
log?: (msg: string) => void;
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface InteractiveReviewOutcome {
|
|
12
|
-
file: string;
|
|
13
|
-
applied: boolean;
|
|
6
|
+
/** Absolute path of the rendered Sela Insights HTML report, when present. */
|
|
7
|
+
reportHtmlPath?: string | null;
|
|
14
8
|
}
|
|
15
9
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* Sequential by design — every prompt `await`s before the next entry is
|
|
21
|
-
* rendered. Concurrent prompts on a single TTY would interleave output.
|
|
10
|
+
* Print the post-run review summary. Returns immediately - never blocks
|
|
11
|
+
* on stdin. Safe to call from the reporter's onEnd() in any environment
|
|
12
|
+
* (TTY, piped CI, IDE-integrated runner).
|
|
22
13
|
*/
|
|
23
|
-
export declare function
|
|
14
|
+
export declare function printHealReview(deps: PrintReviewDeps): void;
|
|
24
15
|
//# sourceMappingURL=InteractiveReview.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractiveReview.d.ts","sourceRoot":"","sources":["../../src/services/InteractiveReview.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InteractiveReview.d.ts","sourceRoot":"","sources":["../../src/services/InteractiveReview.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,uEAAuE;IACvE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA6B3D"}
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// src/services/InteractiveReview.ts
|
|
3
3
|
//
|
|
4
|
-
// Local DX
|
|
4
|
+
// Local DX - Post-run summary printer (MVP write-and-notify).
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// The MVP flow is write-on-disk-then-notify: workers (and the engine)
|
|
7
|
+
// already mutated the source files in-place during execution. The
|
|
8
|
+
// reporter calls printHealReview() at the end purely to display:
|
|
9
|
+
// • a banner with the number of mutated files,
|
|
10
|
+
// • per-file isolated unified diff (clean room - never the working tree),
|
|
11
|
+
// • a vscode://file deeplink to the mutated line,
|
|
12
|
+
// • an optional deeplink to the generated HTML insights report.
|
|
10
13
|
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// deeplink, then prompts the developer. 'Y' / 'y' / Enter keeps the
|
|
14
|
-
// on-disk fix (the worker already wrote it); 'N' / 'n' rewrites the file
|
|
15
|
-
// back to `contentBefore` (the pre-heal state captured by
|
|
16
|
-
// `WorkspaceSnapshotService.preWrite()` in the worker).
|
|
17
|
-
//
|
|
18
|
-
// All I/O is injectable so this can be unit-tested without a real TTY.
|
|
14
|
+
// No prompts. No rollback. No blocking on stdin. SIGINT handling lives
|
|
15
|
+
// in SelaReporter - this module is pure stdout/stderr.
|
|
19
16
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
17
|
if (k2 === undefined) k2 = k;
|
|
21
18
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -53,55 +50,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
53
50
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
54
51
|
};
|
|
55
52
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
-
exports.
|
|
57
|
-
const fs = __importStar(require("fs"));
|
|
53
|
+
exports.printHealReview = printHealReview;
|
|
58
54
|
const path = __importStar(require("path"));
|
|
59
|
-
const readline = __importStar(require("readline"));
|
|
60
55
|
const chalk_1 = __importDefault(require("chalk"));
|
|
61
56
|
const IsolatedDiff_1 = require("../utils/IsolatedDiff");
|
|
62
|
-
const DEFAULT_PROMPT = "[Sela] Apply this fix? (Y/n): ";
|
|
63
57
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* Sequential by design — every prompt `await`s before the next entry is
|
|
69
|
-
* rendered. Concurrent prompts on a single TTY would interleave output.
|
|
58
|
+
* Print the post-run review summary. Returns immediately - never blocks
|
|
59
|
+
* on stdin. Safe to call from the reporter's onEnd() in any environment
|
|
60
|
+
* (TTY, piped CI, IDE-integrated runner).
|
|
70
61
|
*/
|
|
71
|
-
|
|
62
|
+
function printHealReview(deps) {
|
|
72
63
|
const log = deps.log ?? ((m) => process.stdout.write(m + "\n"));
|
|
73
|
-
const prompt = deps.prompt ?? defaultPrompt;
|
|
74
|
-
const rollback = deps.rollback ?? defaultRollback;
|
|
75
64
|
const entries = deps.entries ?? [];
|
|
76
|
-
const
|
|
77
|
-
if (entries.length === 0)
|
|
78
|
-
return
|
|
79
|
-
// Headline banner — surfaces even when downstream chalk/readline
|
|
80
|
-
// output is suppressed by the host terminal multiplexer (e.g.
|
|
81
|
-
// Playwright's reporter-level stdio interception).
|
|
65
|
+
const reportHtmlPath = deps.reportHtmlPath ?? null;
|
|
66
|
+
if (entries.length === 0 && !reportHtmlPath)
|
|
67
|
+
return;
|
|
82
68
|
log("");
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
outcomes.push({ file: entry.absolutePath, applied: true });
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
try {
|
|
94
|
-
rollback(entry);
|
|
95
|
-
log(chalk_1.default.yellow(`[Sela] ↩️ Rolled back: ${entry.relativePath} (restored to pre-heal state)`));
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
log(chalk_1.default.red(`[Sela] ⚠️ Rollback failed for ${entry.relativePath}: ${err.message}`));
|
|
99
|
-
}
|
|
100
|
-
outcomes.push({ file: entry.absolutePath, applied: false });
|
|
69
|
+
if (entries.length > 0) {
|
|
70
|
+
// Count actual healed selectors (a file can hold several), not files.
|
|
71
|
+
const fileCount = entries.length;
|
|
72
|
+
const fixCount = entries.reduce((n, e) => n + (e.healCount ?? 1), 0);
|
|
73
|
+
log(chalk_1.default.bold.bgCyan.black(` [Sela] Local DX Review - ${fixCount} fix${fixCount === 1 ? "" : "es"} applied across ${fileCount} file${fileCount === 1 ? "" : "s"} `));
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
renderEntry(entry, log);
|
|
101
76
|
}
|
|
102
77
|
}
|
|
78
|
+
if (reportHtmlPath) {
|
|
79
|
+
log("");
|
|
80
|
+
log(chalk_1.default.bold(`[Sela] 📄 Insights report:`));
|
|
81
|
+
log(` ${chalk_1.default.cyan(buildFileLink(reportHtmlPath))}`);
|
|
82
|
+
}
|
|
103
83
|
log("");
|
|
104
|
-
return outcomes;
|
|
105
84
|
}
|
|
106
85
|
function renderEntry(entry, log) {
|
|
107
86
|
const fileName = path.basename(entry.absolutePath);
|
|
@@ -113,9 +92,8 @@ function renderEntry(entry, log) {
|
|
|
113
92
|
log("");
|
|
114
93
|
log(colorizeDiff(diff));
|
|
115
94
|
log("");
|
|
116
|
-
log(`👉
|
|
95
|
+
log(`👉 Open in VS Code:`);
|
|
117
96
|
log(` ${chalk_1.default.cyan(buildVsCodeLink(entry.absolutePath, entry.lineNumber))}`);
|
|
118
|
-
log("");
|
|
119
97
|
}
|
|
120
98
|
function colorizeDiff(diff) {
|
|
121
99
|
if (!diff)
|
|
@@ -144,75 +122,7 @@ function buildVsCodeLink(absPath, line) {
|
|
|
144
122
|
? `vscode://file/${normalised}:${line}`
|
|
145
123
|
: `vscode://file/${normalised}`;
|
|
146
124
|
}
|
|
147
|
-
function
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
// Anything else ⇒ apply (default-safe — never silently destroy work).
|
|
151
|
-
if (trimmed === "" || trimmed === "y" || trimmed === "yes")
|
|
152
|
-
return "apply";
|
|
153
|
-
if (trimmed === "n" || trimmed === "no")
|
|
154
|
-
return "reject";
|
|
155
|
-
return "apply";
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Default rollback — rewrites `contentBefore` to disk. Honours the
|
|
159
|
-
* `createdBySela` flag so files Sela CREATED from nothing get unlinked
|
|
160
|
-
* instead of being replaced with an empty buffer.
|
|
161
|
-
*/
|
|
162
|
-
function defaultRollback(entry) {
|
|
163
|
-
if (entry.createdBySela) {
|
|
164
|
-
if (fs.existsSync(entry.absolutePath)) {
|
|
165
|
-
fs.unlinkSync(entry.absolutePath);
|
|
166
|
-
}
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
fs.writeFileSync(entry.absolutePath, entry.contentBefore, "utf8");
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Bind `readline` to the live stdin/stdout. Reporter-only — workers must
|
|
173
|
-
* never reach this code path (they have no TTY and would deadlock).
|
|
174
|
-
*
|
|
175
|
-
* Hardening:
|
|
176
|
-
* • If stdin is not a TTY (CI, non-interactive shell, Playwright reporter
|
|
177
|
-
* context that detached stdio), default to Apply ('y') without blocking.
|
|
178
|
-
* • Explicitly `resume()` stdin — Node pauses it by default once any other
|
|
179
|
-
* consumer (readline-from-an-earlier-iteration, raw-mode toggles) lets go.
|
|
180
|
-
* • Write the prompt to `stderr` so Playwright's stdout summary buffer does
|
|
181
|
-
* not overwrite or strip the question line.
|
|
182
|
-
*/
|
|
183
|
-
function defaultPrompt(question) {
|
|
184
|
-
const stdinIsTty = process.stdin.isTTY === true;
|
|
185
|
-
if (!stdinIsTty) {
|
|
186
|
-
process.stderr.write(question + "y (no TTY — auto-apply)\n");
|
|
187
|
-
return Promise.resolve("y");
|
|
188
|
-
}
|
|
189
|
-
return new Promise((resolve) => {
|
|
190
|
-
try {
|
|
191
|
-
process.stdin.resume();
|
|
192
|
-
}
|
|
193
|
-
catch {
|
|
194
|
-
// Already resumed / not resumable — readline will still try.
|
|
195
|
-
}
|
|
196
|
-
// `terminal: false` reads stdin line-buffered without raw-mode tricks.
|
|
197
|
-
// This is reliable for both real TTYs AND piped harnesses (CI smoke
|
|
198
|
-
// tests, child-process drivers). `terminal: true` only adds history /
|
|
199
|
-
// arrow-key support, which we don't need for a single Y/N prompt and
|
|
200
|
-
// which mis-parses piped input on Windows.
|
|
201
|
-
process.stderr.write(question);
|
|
202
|
-
const rl = readline.createInterface({
|
|
203
|
-
input: process.stdin,
|
|
204
|
-
output: process.stderr,
|
|
205
|
-
terminal: false,
|
|
206
|
-
});
|
|
207
|
-
let settled = false;
|
|
208
|
-
const finalise = (answer) => {
|
|
209
|
-
if (settled)
|
|
210
|
-
return;
|
|
211
|
-
settled = true;
|
|
212
|
-
rl.close();
|
|
213
|
-
resolve(answer);
|
|
214
|
-
};
|
|
215
|
-
rl.once("line", (line) => finalise(line));
|
|
216
|
-
rl.once("close", () => finalise("y"));
|
|
217
|
-
});
|
|
125
|
+
function buildFileLink(absPath) {
|
|
126
|
+
const normalised = absPath.split(path.sep).join("/");
|
|
127
|
+
return `file://${normalised}`;
|
|
218
128
|
}
|
|
@@ -79,7 +79,7 @@ export interface FixResponse {
|
|
|
79
79
|
originalChainHint?: SmartChainSegment[];
|
|
80
80
|
/**
|
|
81
81
|
* Confidence score 0-100. Undefined when the model omitted it or returned a
|
|
82
|
-
* non-finite value
|
|
82
|
+
* non-finite value - downstream code must treat undefined as "unknown" and
|
|
83
83
|
* render "n/a" rather than synthesising a 0.
|
|
84
84
|
*/
|
|
85
85
|
confidence?: number;
|
|
@@ -71,11 +71,11 @@ Narrowing: filter, first, last, nth
|
|
|
71
71
|
You MUST return a "chainSegments" array for the permanent code fix AND a matching "segments" array for the runtime proxy.
|
|
72
72
|
|
|
73
73
|
Build the chain in this priority order:
|
|
74
|
-
PRIORITY 1
|
|
75
|
-
PRIORITY 2
|
|
76
|
-
PRIORITY 3
|
|
77
|
-
PRIORITY 4
|
|
78
|
-
NARROWING
|
|
74
|
+
PRIORITY 1 - getByTestId
|
|
75
|
+
PRIORITY 2 - getByRole (ALWAYS include "name" if it exists in the DOM to ensure uniqueness)
|
|
76
|
+
PRIORITY 3 - getByLabel
|
|
77
|
+
PRIORITY 4 - getByText (use exact: true if possible)
|
|
78
|
+
NARROWING - Use filter({ hasText: "..." }) to isolate an element within a repeated container.
|
|
79
79
|
|
|
80
80
|
### PROXY SELECTOR CONSTRUCTION (segments field)
|
|
81
81
|
The "segments[0].selector" string is used for an immediate "live" retry.
|
|
@@ -90,10 +90,10 @@ Preserve the original code's structural pattern from "originalChainHint":
|
|
|
90
90
|
|
|
91
91
|
### TEMPLATE LITERAL / FUNCTION SELECTOR PRESERVATION
|
|
92
92
|
When the failing selector originates from a Template Literal or a function returning a template,
|
|
93
|
-
preserve the attribute structure
|
|
93
|
+
preserve the attribute structure - update the value inside the attribute rather than removing it.
|
|
94
94
|
For chain selectors: if the original was "#section-B >> input[data-role='user_legacy']"
|
|
95
95
|
and the DNA shows data-role changed to "user_active", return "#section-B >> input[data-role='user_active']".
|
|
96
|
-
NEVER simplify to "#section-B >> input"
|
|
96
|
+
NEVER simplify to "#section-B >> input" - that loses the attribute and breaks automated source healing.
|
|
97
97
|
The healing system depends on the attribute value being present in your response to patch the template variable.
|
|
98
98
|
|
|
99
99
|
### TYPE SAFETY RULES
|
|
@@ -105,21 +105,21 @@ If the element's text changed, you MUST include:
|
|
|
105
105
|
"contentChange": { "oldText": "<previous>", "newText": "<current>" }
|
|
106
106
|
|
|
107
107
|
### CONFIDENCE SCORE (MANDATORY)
|
|
108
|
-
You MUST include a numeric "confidence" field
|
|
108
|
+
You MUST include a numeric "confidence" field - an INTEGER in the range 0-100 -
|
|
109
109
|
representing how certain you are that the returned chain will resolve the
|
|
110
110
|
intended element on the next test run. Use this rubric:
|
|
111
|
-
- 90-100: stable id, data-testid, or unique role+name
|
|
111
|
+
- 90-100: stable id, data-testid, or unique role+name - zero ambiguity in the DOM.
|
|
112
112
|
- 70-89: strong semantic match, but some structural drift or competing candidates.
|
|
113
|
-
- 50-69: best-guess match
|
|
114
|
-
- 1-49: speculative match
|
|
113
|
+
- 50-69: best-guess match - multiple plausible candidates required disambiguation.
|
|
114
|
+
- 1-49: speculative match - return this only when no better candidate exists.
|
|
115
115
|
NEVER omit this field. NEVER return it as a string, boolean, or null.
|
|
116
|
-
Reports rendered downstream will show "n/a" when this field is missing
|
|
116
|
+
Reports rendered downstream will show "n/a" when this field is missing - which
|
|
117
117
|
is a clear failure signal to the developer reviewing the heal.
|
|
118
118
|
|
|
119
119
|
### MANDATORY OUTPUT FORMAT
|
|
120
120
|
Return ONLY valid JSON.
|
|
121
121
|
|
|
122
|
-
Example output
|
|
122
|
+
Example output - Identifying a specific button in a list row:
|
|
123
123
|
{
|
|
124
124
|
"status": "FIXED",
|
|
125
125
|
"confidence": 92,
|
|
@@ -215,7 +215,7 @@ class LLMService {
|
|
|
215
215
|
throw new SelaError_1.SelaError({
|
|
216
216
|
subsystem: "LLMService",
|
|
217
217
|
code: SelaError_1.LLM_SERVICE_CODES.NO_API_KEY,
|
|
218
|
-
reason: "ANTHROPIC_API_KEY not found
|
|
218
|
+
reason: "ANTHROPIC_API_KEY not found - pass an `anthropic` client or `apiKey` to LLMService(), or set the env var",
|
|
219
219
|
});
|
|
220
220
|
}
|
|
221
221
|
this.anthropic = new sdk_1.default({ apiKey });
|
|
@@ -339,7 +339,7 @@ ${request.targetIntent}
|
|
|
339
339
|
### PREVIOUS DNA (Element Fingerprint):
|
|
340
340
|
${dnaSummary && Object.keys(dnaSummary).length > 0
|
|
341
341
|
? JSON.stringify(dnaSummary, null, 2)
|
|
342
|
-
: "NO DNA (First run
|
|
342
|
+
: "NO DNA (First run - infer from selector and DOM)"}
|
|
343
343
|
|
|
344
344
|
### CURRENT DOM SNIPPET:
|
|
345
345
|
${request.currentDom}
|
|
@@ -351,7 +351,7 @@ ${request.currentDom}
|
|
|
351
351
|
4. Populate "contentChange" if the element's visible text changed.
|
|
352
352
|
5. Also populate "segments" (legacy format) for backward compatibility.
|
|
353
353
|
|
|
354
|
-
Return ONLY a raw JSON object
|
|
354
|
+
Return ONLY a raw JSON object - no markdown, no preamble.`;
|
|
355
355
|
try {
|
|
356
356
|
const msg = await this.anthropic.messages.create({
|
|
357
357
|
model: this.model,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { AnchorKey, SourceSpan } from "./AnchorResolver";
|
|
2
|
+
/**
|
|
3
|
+
* A single edit. `replace` edits carry an `anchor` and are RE-RESOLVED at
|
|
4
|
+
* apply-time (span recomputed from the fresh parse). `insert` edits (forks)
|
|
5
|
+
* carry a literal `span` computed against the same content being applied.
|
|
6
|
+
*/
|
|
7
|
+
export interface AnchoredEdit {
|
|
8
|
+
kind: "replace" | "insert";
|
|
9
|
+
replacement: string;
|
|
10
|
+
/** Replace target — re-resolved via resolveAnchor at apply time. */
|
|
11
|
+
anchor?: AnchorKey;
|
|
12
|
+
/** Literal span for inserts (and as a fallback for anchorless replaces). */
|
|
13
|
+
span?: SourceSpan;
|
|
14
|
+
/**
|
|
15
|
+
* Require the replacement to be a Locator-returning expression. Defaults to
|
|
16
|
+
* true for `replace`. Set false for inserts / non-locator edits.
|
|
17
|
+
*/
|
|
18
|
+
requireLocator?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface FileBatch {
|
|
21
|
+
filePath: string;
|
|
22
|
+
edits: AnchoredEdit[];
|
|
23
|
+
}
|
|
24
|
+
export type ApplyStatus = "applied" | "rolled-back" | "no-op" | "skipped";
|
|
25
|
+
export interface ApplyOutcome {
|
|
26
|
+
filePath: string;
|
|
27
|
+
status: ApplyStatus;
|
|
28
|
+
reason: string;
|
|
29
|
+
written: boolean;
|
|
30
|
+
/** Content after the run — the new content when applied, else the original. */
|
|
31
|
+
finalContent: string;
|
|
32
|
+
/** Edits that could not be applied (stale anchor, type-incompat, …). */
|
|
33
|
+
skipped: Array<{
|
|
34
|
+
reason: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export interface ApplyOptions {
|
|
38
|
+
/** When false, compute + gate but never touch disk. Default true. */
|
|
39
|
+
write?: boolean;
|
|
40
|
+
/** Honour SELA_DRY_RUN by leaving disk untouched. Default true. */
|
|
41
|
+
respectDryRun?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export declare class MutationApplier {
|
|
44
|
+
/** Apply many batches; each file is processed independently. */
|
|
45
|
+
static applyBatches(batches: FileBatch[], opts?: ApplyOptions): ApplyOutcome[];
|
|
46
|
+
static applyFileBatch(batch: FileBatch, opts?: ApplyOptions): ApplyOutcome;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Cheap return-type pre-check. The replacement must be an expression whose
|
|
50
|
+
* OUTERMOST call is a Locator-returning Playwright method (locator / getBy* /
|
|
51
|
+
* frameLocator / nth / first / last / filter / and / or). Rejects actions
|
|
52
|
+
* (.click()), string queries (.title(), .textContent()), bare literals, etc.
|
|
53
|
+
*/
|
|
54
|
+
export declare function isLocatorReturningExpr(text: string): boolean;
|
|
55
|
+
//# sourceMappingURL=MutationApplier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MutationApplier.d.ts","sourceRoot":"","sources":["../../src/services/MutationApplier.ts"],"names":[],"mappings":"AA2BA,OAAO,EACL,SAAS,EAET,UAAU,EACX,MAAM,kBAAkB,CAAC;AAS1B;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;AAE1E,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mEAAmE;IACnE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAeD,qBAAa,eAAe;IAC1B,gEAAgE;IAChE,MAAM,CAAC,YAAY,CACjB,OAAO,EAAE,SAAS,EAAE,EACpB,IAAI,GAAE,YAAiB,GACtB,YAAY,EAAE;IAIjB,MAAM,CAAC,cAAc,CACnB,KAAK,EAAE,SAAS,EAChB,IAAI,GAAE,YAAiB,GACtB,YAAY;CA6JhB;AA2CD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkB5D"}
|