sela-core 1.0.6 → 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.
- package/README.md +1 -1
- 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/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 +9 -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 +3 -2
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +23 -13
- package/dist/config/DryRunGuard.d.ts +14 -0
- package/dist/config/DryRunGuard.d.ts.map +1 -0
- package/dist/config/DryRunGuard.js +79 -0
- package/dist/config/SelaConfig.d.ts +26 -16
- package/dist/config/SelaConfig.d.ts.map +1 -1
- package/dist/config/SelaConfig.js +54 -22
- package/dist/engine/HealingRegistry.d.ts +1 -1
- package/dist/engine/HealingRegistry.js +3 -3
- package/dist/engine/SelaEngine.d.ts +13 -10
- package/dist/engine/SelaEngine.d.ts.map +1 -1
- package/dist/engine/SelaEngine.js +292 -101
- package/dist/errors/SelaError.d.ts +132 -0
- package/dist/errors/SelaError.d.ts.map +1 -0
- package/dist/errors/SelaError.js +154 -0
- package/dist/fixtures/expectProxy.d.ts +1 -1
- package/dist/fixtures/expectProxy.d.ts.map +1 -1
- package/dist/fixtures/expectProxy.js +17 -10
- package/dist/fixtures/index.d.ts +7 -1
- package/dist/fixtures/index.d.ts.map +1 -1
- package/dist/fixtures/index.js +26 -11
- package/dist/fixtures/proxyTag.d.ts +12 -0
- package/dist/fixtures/proxyTag.d.ts.map +1 -0
- package/dist/fixtures/proxyTag.js +45 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -4
- package/dist/reporter/SelaReporter.d.ts +143 -0
- package/dist/reporter/SelaReporter.d.ts.map +1 -0
- package/dist/reporter/SelaReporter.js +428 -0
- package/dist/services/ASTSourceUpdater.d.ts +20 -1
- package/dist/services/ASTSourceUpdater.d.ts.map +1 -1
- package/dist/services/ASTSourceUpdater.js +257 -89
- 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/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 +43 -1
- package/dist/services/HealReportService.d.ts.map +1 -1
- package/dist/services/HealReportService.js +108 -25
- package/dist/services/HealingAdvisory.js +1 -1
- package/dist/services/HealingCacheService.d.ts +135 -0
- package/dist/services/HealingCacheService.d.ts.map +1 -0
- package/dist/services/HealingCacheService.js +460 -0
- 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 +20 -1
- package/dist/services/IntentAuditor.d.ts +18 -1
- package/dist/services/IntentAuditor.d.ts.map +1 -1
- package/dist/services/IntentAuditor.js +50 -26
- package/dist/services/InteractiveReview.d.ts +15 -0
- package/dist/services/InteractiveReview.d.ts.map +1 -0
- package/dist/services/InteractiveReview.js +125 -0
- package/dist/services/LLMService.d.ts +18 -2
- package/dist/services/LLMService.d.ts.map +1 -1
- package/dist/services/LLMService.js +33 -23
- package/dist/services/PRAutomationService.d.ts +14 -1
- package/dist/services/PRAutomationService.d.ts.map +1 -1
- package/dist/services/PRAutomationService.js +287 -92
- package/dist/services/PendingPromptLedger.d.ts +44 -0
- package/dist/services/PendingPromptLedger.d.ts.map +1 -0
- package/dist/services/PendingPromptLedger.js +180 -0
- package/dist/services/ReportGenerator.d.ts +70 -0
- package/dist/services/ReportGenerator.d.ts.map +1 -0
- package/dist/services/ReportGenerator.js +191 -0
- package/dist/services/SafetyGuard.d.ts +30 -7
- package/dist/services/SafetyGuard.d.ts.map +1 -1
- package/dist/services/SafetyGuard.js +85 -116
- package/dist/services/SnapshotService.js +5 -5
- 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 +66 -34
- package/dist/services/TemplateDiffService.d.ts.map +1 -1
- package/dist/services/TemplateDiffService.js +18 -15
- package/dist/services/WorkspaceSnapshotService.d.ts +71 -0
- package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -0
- package/dist/services/WorkspaceSnapshotService.js +200 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/IsolatedDiff.d.ts +45 -0
- package/dist/utils/IsolatedDiff.d.ts.map +1 -0
- package/dist/utils/IsolatedDiff.js +382 -0
- package/package.json +71 -67
|
@@ -46,15 +46,15 @@ dotenv.config();
|
|
|
46
46
|
const FALLBACK_VERDICT = {
|
|
47
47
|
verdict: "SUSPICIOUS",
|
|
48
48
|
confidence: 0,
|
|
49
|
-
reason: "Auditor unavailable
|
|
49
|
+
reason: "Auditor unavailable - defaulting to cautious SUSPICIOUS verdict",
|
|
50
50
|
inversionType: null,
|
|
51
51
|
};
|
|
52
52
|
// Ancestry drift penalties (spec §2.1).
|
|
53
53
|
// Applied as negative adjustments to the LLM's confidence score.
|
|
54
54
|
// Maximum combined penalty: −30 pts.
|
|
55
55
|
const DRIFT_PENALTIES = [
|
|
56
|
-
{ full: -20, partial: -10 }, // depth 1
|
|
57
|
-
{ full: -10, partial: -5 }, // depth 2
|
|
56
|
+
{ full: -20, partial: -10 }, // depth 1 - direct parent
|
|
57
|
+
{ full: -10, partial: -5 }, // depth 2 - grandparent
|
|
58
58
|
];
|
|
59
59
|
// Anchor bonuses: positive-only (spec §3.3).
|
|
60
60
|
// closestLabel exact match: +10 pts
|
|
@@ -85,8 +85,8 @@ RULES:
|
|
|
85
85
|
3. Minor reformatting is irrelevant. "Save Changes" and "Save" are CONSISTENT.
|
|
86
86
|
4. Role/aria context matters. A button that was "Submit" becoming "Cancel" is INCONSISTENT (identity inversion).
|
|
87
87
|
5. When both texts are very short (3 chars or less) and differ, prefer SUSPICIOUS unless an obvious opposite pair.
|
|
88
|
-
6. In "assertion" mode, be stricter
|
|
89
|
-
7. In "action" mode, be more lenient
|
|
88
|
+
6. In "assertion" mode, be stricter - lean toward SUSPICIOUS or INCONSISTENT when the change is ambiguous.
|
|
89
|
+
7. In "action" mode, be more lenient - lean toward CONSISTENT when the change looks like a UI refactor.
|
|
90
90
|
|
|
91
91
|
RESPONSE FORMAT (strict JSON, no other text):
|
|
92
92
|
{
|
|
@@ -95,16 +95,29 @@ RESPONSE FORMAT (strict JSON, no other text):
|
|
|
95
95
|
"reason": "<one sentence explaining the verdict>",
|
|
96
96
|
"inversionType": "polarity" | "quantitative" | "state" | "identity" | null
|
|
97
97
|
}`;
|
|
98
|
-
|
|
99
|
-
// IntentAuditor
|
|
100
|
-
// ═══════════════════════════════════════════════════════════════════
|
|
98
|
+
const DEFAULT_AUDITOR_MODEL = "claude-haiku-4-5-20251001";
|
|
101
99
|
class IntentAuditor {
|
|
102
100
|
anthropic;
|
|
103
101
|
disabled;
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
model;
|
|
103
|
+
constructor(opts = {}) {
|
|
104
|
+
this.model = opts.model ?? DEFAULT_AUDITOR_MODEL;
|
|
105
|
+
// Explicit `null` from the caller forces disabled mode - used by tests.
|
|
106
|
+
if (opts.anthropic === null) {
|
|
107
|
+
this.anthropic = null;
|
|
108
|
+
this.disabled = true;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Caller supplied a ready-to-use client → use it as-is.
|
|
112
|
+
if (opts.anthropic !== undefined) {
|
|
113
|
+
this.anthropic = opts.anthropic;
|
|
114
|
+
this.disabled = false;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// Otherwise fall back to env-based construction (legacy default).
|
|
118
|
+
const apiKey = opts.apiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
106
119
|
if (!apiKey) {
|
|
107
|
-
console.warn("[IntentAuditor] ANTHROPIC_API_KEY not set
|
|
120
|
+
console.warn("[IntentAuditor] ANTHROPIC_API_KEY not set - auditor disabled, will return SUSPICIOUS for all audited heals");
|
|
108
121
|
this.anthropic = null;
|
|
109
122
|
this.disabled = true;
|
|
110
123
|
}
|
|
@@ -128,7 +141,7 @@ class IntentAuditor {
|
|
|
128
141
|
.join("\n");
|
|
129
142
|
try {
|
|
130
143
|
const response = await this.anthropic.messages.create({
|
|
131
|
-
model:
|
|
144
|
+
model: this.model,
|
|
132
145
|
max_tokens: 256,
|
|
133
146
|
temperature: 0.1,
|
|
134
147
|
system: SYSTEM_PROMPT,
|
|
@@ -141,7 +154,7 @@ class IntentAuditor {
|
|
|
141
154
|
// ── Structural scoring ────────────────────────────────────────
|
|
142
155
|
// Apply ancestry drift penalty and anchor bonus to the LLM's raw
|
|
143
156
|
// confidence. The semantic verdict category (CONSISTENT / SUSPICIOUS /
|
|
144
|
-
// INCONSISTENT) is never changed by scoring
|
|
157
|
+
// INCONSISTENT) is never changed by scoring - only the confidence value.
|
|
145
158
|
// The low-confidence CONSISTENT→SUSPICIOUS downgrade is re-evaluated
|
|
146
159
|
// after scoring so the adjusted value is used for the threshold.
|
|
147
160
|
const penalty = this.computeAncestryPenalty(req.dnaAncestry ?? [], req.liveAncestry ?? []);
|
|
@@ -159,7 +172,11 @@ class IntentAuditor {
|
|
|
159
172
|
// Re-apply low-confidence CONSISTENT downgrade with the adjusted value.
|
|
160
173
|
// The raw check in parseVerdict used the pre-adjustment confidence; a
|
|
161
174
|
// penalty may push a borderline CONSISTENT below the 50% threshold.
|
|
162
|
-
const scoring = {
|
|
175
|
+
const scoring = {
|
|
176
|
+
rawConfidence: rawVerdict.confidence,
|
|
177
|
+
penalty,
|
|
178
|
+
bonus,
|
|
179
|
+
};
|
|
163
180
|
if (rawVerdict.verdict === "CONSISTENT" && adjConf < 50) {
|
|
164
181
|
finalVerdict = {
|
|
165
182
|
verdict: "SUSPICIOUS",
|
|
@@ -171,22 +188,29 @@ class IntentAuditor {
|
|
|
171
188
|
console.log(`[IntentAuditor] CONSISTENT→SUSPICIOUS after scoring (${rawVerdict.confidence}%→${adjConf}%)`);
|
|
172
189
|
}
|
|
173
190
|
else {
|
|
174
|
-
finalVerdict = {
|
|
191
|
+
finalVerdict = {
|
|
192
|
+
...rawVerdict,
|
|
193
|
+
confidence: adjConf,
|
|
194
|
+
scoreBreakdown: scoring,
|
|
195
|
+
};
|
|
175
196
|
}
|
|
176
197
|
}
|
|
177
198
|
else {
|
|
178
199
|
finalVerdict = rawVerdict;
|
|
179
200
|
}
|
|
180
|
-
console.log(`[IntentAuditor] verdict=${finalVerdict.verdict} (${finalVerdict.confidence}%)
|
|
201
|
+
console.log(`[IntentAuditor] verdict=${finalVerdict.verdict} (${finalVerdict.confidence}%) - ${finalVerdict.reason}`);
|
|
181
202
|
return finalVerdict;
|
|
182
203
|
}
|
|
183
204
|
catch (err) {
|
|
184
|
-
console.warn(`[IntentAuditor] Warning: Auditor call failed: ${err.message}
|
|
185
|
-
return {
|
|
205
|
+
console.warn(`[IntentAuditor] Warning: Auditor call failed: ${err.message} - returning SUSPICIOUS`);
|
|
206
|
+
return {
|
|
207
|
+
...FALLBACK_VERDICT,
|
|
208
|
+
reason: `Auditor call failed: ${err.message}`,
|
|
209
|
+
};
|
|
186
210
|
}
|
|
187
211
|
}
|
|
188
212
|
// ─────────────────────────────────────────────────────────────
|
|
189
|
-
// computeAncestryPenalty
|
|
213
|
+
// computeAncestryPenalty - DNA v2 Ancestry Drift (spec §2)
|
|
190
214
|
//
|
|
191
215
|
// Compares at most 2 ancestor depths between the DNA baseline and
|
|
192
216
|
// the live candidate. Returns a value in [−30, 0]; 0 = no drift.
|
|
@@ -203,7 +227,7 @@ class IntentAuditor {
|
|
|
203
227
|
// ─────────────────────────────────────────────────────────────
|
|
204
228
|
computeAncestryPenalty(dnaPath, livePath) {
|
|
205
229
|
if (dnaPath.length === 0)
|
|
206
|
-
return 0; // v1 migrated snapshot
|
|
230
|
+
return 0; // v1 migrated snapshot - skip
|
|
207
231
|
let totalPenalty = 0;
|
|
208
232
|
const maxDepth = Math.min(dnaPath.length, livePath.length, 2);
|
|
209
233
|
for (let i = 0; i < maxDepth; i++) {
|
|
@@ -216,21 +240,21 @@ class IntentAuditor {
|
|
|
216
240
|
const depthLabel = i === 0 ? "depth-1 (parent)" : "depth-2 (grandparent)";
|
|
217
241
|
if (dna.tag !== live.tag) {
|
|
218
242
|
totalPenalty += full;
|
|
219
|
-
console.log(`[IntentAuditor] 🏗️ Ancestry drift ${full} pts
|
|
243
|
+
console.log(`[IntentAuditor] 🏗️ Ancestry drift ${full} pts - ${depthLabel}: ` +
|
|
220
244
|
`tag mismatch (${dna.fingerprint} → ${live.fingerprint})`);
|
|
221
245
|
}
|
|
222
246
|
else {
|
|
223
247
|
totalPenalty += partial;
|
|
224
|
-
console.log(`[IntentAuditor] 🏗️ Ancestry drift ${partial} pts
|
|
248
|
+
console.log(`[IntentAuditor] 🏗️ Ancestry drift ${partial} pts - ${depthLabel}: ` +
|
|
225
249
|
`same tag, id/class changed (${dna.fingerprint} → ${live.fingerprint})`);
|
|
226
250
|
}
|
|
227
251
|
}
|
|
228
252
|
return totalPenalty;
|
|
229
253
|
}
|
|
230
254
|
// ─────────────────────────────────────────────────────────────
|
|
231
|
-
// computeAnchorBonus
|
|
255
|
+
// computeAnchorBonus - DNA v2 Anchor Confirmation (spec §3.3)
|
|
232
256
|
//
|
|
233
|
-
// Anchors only provide positive confirmation
|
|
257
|
+
// Anchors only provide positive confirmation - no penalty for
|
|
234
258
|
// mismatch. Returns a value in [0, +15].
|
|
235
259
|
//
|
|
236
260
|
// closestLabel exact match (case-insensitive): +10 pts
|
|
@@ -244,13 +268,13 @@ class IntentAuditor {
|
|
|
244
268
|
const liveLabel = liveAnchors.closestLabel?.toLowerCase().trim();
|
|
245
269
|
if (dnaLabel && liveLabel && dnaLabel === liveLabel) {
|
|
246
270
|
bonus += ANCHOR_BONUS_LABEL;
|
|
247
|
-
console.log(`[IntentAuditor] 🎯 Anchor +${ANCHOR_BONUS_LABEL} pts
|
|
271
|
+
console.log(`[IntentAuditor] 🎯 Anchor +${ANCHOR_BONUS_LABEL} pts - closestLabel match: "${dnaAnchors.closestLabel}"`);
|
|
248
272
|
}
|
|
249
273
|
const dnaRow = dnaAnchors.rowAnchor?.toLowerCase().trim();
|
|
250
274
|
const liveRow = liveAnchors.rowAnchor?.toLowerCase().trim();
|
|
251
275
|
if (dnaRow && liveRow && dnaRow === liveRow) {
|
|
252
276
|
bonus += ANCHOR_BONUS_ROW;
|
|
253
|
-
console.log(`[IntentAuditor] 🎯 Anchor +${ANCHOR_BONUS_ROW} pts
|
|
277
|
+
console.log(`[IntentAuditor] 🎯 Anchor +${ANCHOR_BONUS_ROW} pts - rowAnchor match: "${dnaAnchors.rowAnchor}"`);
|
|
254
278
|
}
|
|
255
279
|
return bonus;
|
|
256
280
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PendingPromptEntry } from "./PendingPromptLedger";
|
|
2
|
+
export interface PrintReviewDeps {
|
|
3
|
+
entries: PendingPromptEntry[];
|
|
4
|
+
/** Override the console sink - tests capture output for assertions. */
|
|
5
|
+
log?: (msg: string) => void;
|
|
6
|
+
/** Absolute path of the rendered Sela Insights HTML report, when present. */
|
|
7
|
+
reportHtmlPath?: string | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
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).
|
|
13
|
+
*/
|
|
14
|
+
export declare function printHealReview(deps: PrintReviewDeps): void;
|
|
15
|
+
//# sourceMappingURL=InteractiveReview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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,CA0B3D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/services/InteractiveReview.ts
|
|
3
|
+
//
|
|
4
|
+
// Local DX - Post-run summary printer (MVP write-and-notify).
|
|
5
|
+
//
|
|
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.
|
|
13
|
+
//
|
|
14
|
+
// No prompts. No rollback. No blocking on stdin. SIGINT handling lives
|
|
15
|
+
// in SelaReporter - this module is pure stdout/stderr.
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
50
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.printHealReview = printHealReview;
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
56
|
+
const IsolatedDiff_1 = require("../utils/IsolatedDiff");
|
|
57
|
+
/**
|
|
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).
|
|
61
|
+
*/
|
|
62
|
+
function printHealReview(deps) {
|
|
63
|
+
const log = deps.log ?? ((m) => process.stdout.write(m + "\n"));
|
|
64
|
+
const entries = deps.entries ?? [];
|
|
65
|
+
const reportHtmlPath = deps.reportHtmlPath ?? null;
|
|
66
|
+
if (entries.length === 0 && !reportHtmlPath)
|
|
67
|
+
return;
|
|
68
|
+
log("");
|
|
69
|
+
if (entries.length > 0) {
|
|
70
|
+
log(chalk_1.default.bold.bgCyan.black(` [Sela] Local DX Review - ${entries.length} fix${entries.length === 1 ? "" : "es"} applied to disk `));
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
renderEntry(entry, log);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (reportHtmlPath) {
|
|
76
|
+
log("");
|
|
77
|
+
log(chalk_1.default.bold(`[Sela] 📄 Insights report:`));
|
|
78
|
+
log(` ${chalk_1.default.cyan(buildFileLink(reportHtmlPath))}`);
|
|
79
|
+
}
|
|
80
|
+
log("");
|
|
81
|
+
}
|
|
82
|
+
function renderEntry(entry, log) {
|
|
83
|
+
const fileName = path.basename(entry.absolutePath);
|
|
84
|
+
const diff = (0, IsolatedDiff_1.generateUnifiedDiff)(entry.contentBefore, entry.contentAfter, {
|
|
85
|
+
filePath: entry.relativePath,
|
|
86
|
+
});
|
|
87
|
+
log("");
|
|
88
|
+
log(chalk_1.default.bold(`[Sela] 🔧 Healed selector in ${fileName}`));
|
|
89
|
+
log("");
|
|
90
|
+
log(colorizeDiff(diff));
|
|
91
|
+
log("");
|
|
92
|
+
log(`👉 Open in VS Code:`);
|
|
93
|
+
log(` ${chalk_1.default.cyan(buildVsCodeLink(entry.absolutePath, entry.lineNumber))}`);
|
|
94
|
+
}
|
|
95
|
+
function colorizeDiff(diff) {
|
|
96
|
+
if (!diff)
|
|
97
|
+
return chalk_1.default.dim("(no diff)");
|
|
98
|
+
return diff
|
|
99
|
+
.split("\n")
|
|
100
|
+
.map((row) => {
|
|
101
|
+
if (row.startsWith("+++") ||
|
|
102
|
+
row.startsWith("---") ||
|
|
103
|
+
row.startsWith("diff --git")) {
|
|
104
|
+
return chalk_1.default.bold(row);
|
|
105
|
+
}
|
|
106
|
+
if (row.startsWith("@@"))
|
|
107
|
+
return chalk_1.default.cyan(row);
|
|
108
|
+
if (row.startsWith("+"))
|
|
109
|
+
return chalk_1.default.green(row);
|
|
110
|
+
if (row.startsWith("-"))
|
|
111
|
+
return chalk_1.default.red(row);
|
|
112
|
+
return row;
|
|
113
|
+
})
|
|
114
|
+
.join("\n");
|
|
115
|
+
}
|
|
116
|
+
function buildVsCodeLink(absPath, line) {
|
|
117
|
+
const normalised = absPath.split(path.sep).join("/");
|
|
118
|
+
return line && line > 0
|
|
119
|
+
? `vscode://file/${normalised}:${line}`
|
|
120
|
+
: `vscode://file/${normalised}`;
|
|
121
|
+
}
|
|
122
|
+
function buildFileLink(absPath) {
|
|
123
|
+
const normalised = absPath.split(path.sep).join("/");
|
|
124
|
+
return `file://${normalised}`;
|
|
125
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
1
2
|
import { FixRequest } from "../types";
|
|
2
3
|
export interface SelectorSegment {
|
|
3
4
|
type: "frame" | "element";
|
|
@@ -78,7 +79,7 @@ export interface FixResponse {
|
|
|
78
79
|
originalChainHint?: SmartChainSegment[];
|
|
79
80
|
/**
|
|
80
81
|
* Confidence score 0-100. Undefined when the model omitted it or returned a
|
|
81
|
-
* non-finite value
|
|
82
|
+
* non-finite value - downstream code must treat undefined as "unknown" and
|
|
82
83
|
* render "n/a" rather than synthesising a 0.
|
|
83
84
|
*/
|
|
84
85
|
confidence?: number;
|
|
@@ -86,9 +87,24 @@ export interface FixResponse {
|
|
|
86
87
|
new_selector?: string | null;
|
|
87
88
|
contentChange?: ContentChange;
|
|
88
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Constructor options for LLMService.
|
|
92
|
+
*
|
|
93
|
+
* - `anthropic`: pre-built Anthropic client. Tests use this to inject a
|
|
94
|
+
* mock client without touching env vars or network.
|
|
95
|
+
* - `apiKey`: override the env-based ANTHROPIC_API_KEY when constructing
|
|
96
|
+
* the default client.
|
|
97
|
+
* - `model`: override the Sonnet model id (lets tests pin the SDK call).
|
|
98
|
+
*/
|
|
99
|
+
export interface LLMServiceOptions {
|
|
100
|
+
anthropic?: Anthropic;
|
|
101
|
+
apiKey?: string;
|
|
102
|
+
model?: string;
|
|
103
|
+
}
|
|
89
104
|
export declare class LLMService {
|
|
90
105
|
private anthropic;
|
|
91
|
-
|
|
106
|
+
private readonly model;
|
|
107
|
+
constructor(opts?: LLMServiceOptions);
|
|
92
108
|
private cleanJson;
|
|
93
109
|
/**
|
|
94
110
|
* Attempts to infer contentChange when the AI did not return the field.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LLMService.d.ts","sourceRoot":"","sources":["../../src/services/LLMService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LLMService.d.ts","sourceRoot":"","sources":["../../src/services/LLMService.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.LLMService = void 0;
|
|
40
40
|
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
41
41
|
const dotenv = __importStar(require("dotenv"));
|
|
42
|
+
const SelaError_1 = require("../errors/SelaError");
|
|
42
43
|
dotenv.config();
|
|
43
44
|
// ─────────────────────────────────────────────────────────────────
|
|
44
45
|
// SYSTEM PROMPT
|
|
@@ -70,11 +71,11 @@ Narrowing: filter, first, last, nth
|
|
|
70
71
|
You MUST return a "chainSegments" array for the permanent code fix AND a matching "segments" array for the runtime proxy.
|
|
71
72
|
|
|
72
73
|
Build the chain in this priority order:
|
|
73
|
-
PRIORITY 1
|
|
74
|
-
PRIORITY 2
|
|
75
|
-
PRIORITY 3
|
|
76
|
-
PRIORITY 4
|
|
77
|
-
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.
|
|
78
79
|
|
|
79
80
|
### PROXY SELECTOR CONSTRUCTION (segments field)
|
|
80
81
|
The "segments[0].selector" string is used for an immediate "live" retry.
|
|
@@ -89,10 +90,10 @@ Preserve the original code's structural pattern from "originalChainHint":
|
|
|
89
90
|
|
|
90
91
|
### TEMPLATE LITERAL / FUNCTION SELECTOR PRESERVATION
|
|
91
92
|
When the failing selector originates from a Template Literal or a function returning a template,
|
|
92
|
-
preserve the attribute structure
|
|
93
|
+
preserve the attribute structure - update the value inside the attribute rather than removing it.
|
|
93
94
|
For chain selectors: if the original was "#section-B >> input[data-role='user_legacy']"
|
|
94
95
|
and the DNA shows data-role changed to "user_active", return "#section-B >> input[data-role='user_active']".
|
|
95
|
-
NEVER simplify to "#section-B >> input"
|
|
96
|
+
NEVER simplify to "#section-B >> input" - that loses the attribute and breaks automated source healing.
|
|
96
97
|
The healing system depends on the attribute value being present in your response to patch the template variable.
|
|
97
98
|
|
|
98
99
|
### TYPE SAFETY RULES
|
|
@@ -104,21 +105,21 @@ If the element's text changed, you MUST include:
|
|
|
104
105
|
"contentChange": { "oldText": "<previous>", "newText": "<current>" }
|
|
105
106
|
|
|
106
107
|
### CONFIDENCE SCORE (MANDATORY)
|
|
107
|
-
You MUST include a numeric "confidence" field
|
|
108
|
+
You MUST include a numeric "confidence" field - an INTEGER in the range 0-100 -
|
|
108
109
|
representing how certain you are that the returned chain will resolve the
|
|
109
110
|
intended element on the next test run. Use this rubric:
|
|
110
|
-
- 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.
|
|
111
112
|
- 70-89: strong semantic match, but some structural drift or competing candidates.
|
|
112
|
-
- 50-69: best-guess match
|
|
113
|
-
- 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.
|
|
114
115
|
NEVER omit this field. NEVER return it as a string, boolean, or null.
|
|
115
|
-
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
|
|
116
117
|
is a clear failure signal to the developer reviewing the heal.
|
|
117
118
|
|
|
118
119
|
### MANDATORY OUTPUT FORMAT
|
|
119
120
|
Return ONLY valid JSON.
|
|
120
121
|
|
|
121
|
-
Example output
|
|
122
|
+
Example output - Identifying a specific button in a list row:
|
|
122
123
|
{
|
|
123
124
|
"status": "FIXED",
|
|
124
125
|
"confidence": 92,
|
|
@@ -199,15 +200,24 @@ function inferOriginalChainHint(selector) {
|
|
|
199
200
|
}
|
|
200
201
|
return segments;
|
|
201
202
|
}
|
|
202
|
-
|
|
203
|
-
// LLM SERVICE
|
|
204
|
-
// ─────────────────────────────────────────────────────────────────
|
|
203
|
+
const DEFAULT_LLM_MODEL = "claude-sonnet-4-20250514";
|
|
205
204
|
class LLMService {
|
|
206
205
|
anthropic;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
206
|
+
model;
|
|
207
|
+
constructor(opts = {}) {
|
|
208
|
+
this.model = opts.model ?? DEFAULT_LLM_MODEL;
|
|
209
|
+
if (opts.anthropic) {
|
|
210
|
+
this.anthropic = opts.anthropic;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const apiKey = opts.apiKey ?? process.env.ANTHROPIC_API_KEY ?? "";
|
|
214
|
+
if (!apiKey) {
|
|
215
|
+
throw new SelaError_1.SelaError({
|
|
216
|
+
subsystem: "LLMService",
|
|
217
|
+
code: SelaError_1.LLM_SERVICE_CODES.NO_API_KEY,
|
|
218
|
+
reason: "ANTHROPIC_API_KEY not found - pass an `anthropic` client or `apiKey` to LLMService(), or set the env var",
|
|
219
|
+
});
|
|
220
|
+
}
|
|
211
221
|
this.anthropic = new sdk_1.default({ apiKey });
|
|
212
222
|
}
|
|
213
223
|
cleanJson(text) {
|
|
@@ -329,7 +339,7 @@ ${request.targetIntent}
|
|
|
329
339
|
### PREVIOUS DNA (Element Fingerprint):
|
|
330
340
|
${dnaSummary && Object.keys(dnaSummary).length > 0
|
|
331
341
|
? JSON.stringify(dnaSummary, null, 2)
|
|
332
|
-
: "NO DNA (First run
|
|
342
|
+
: "NO DNA (First run - infer from selector and DOM)"}
|
|
333
343
|
|
|
334
344
|
### CURRENT DOM SNIPPET:
|
|
335
345
|
${request.currentDom}
|
|
@@ -341,10 +351,10 @@ ${request.currentDom}
|
|
|
341
351
|
4. Populate "contentChange" if the element's visible text changed.
|
|
342
352
|
5. Also populate "segments" (legacy format) for backward compatibility.
|
|
343
353
|
|
|
344
|
-
Return ONLY a raw JSON object
|
|
354
|
+
Return ONLY a raw JSON object - no markdown, no preamble.`;
|
|
345
355
|
try {
|
|
346
356
|
const msg = await this.anthropic.messages.create({
|
|
347
|
-
model:
|
|
357
|
+
model: this.model,
|
|
348
358
|
max_tokens: 1024,
|
|
349
359
|
system: SYSTEM_PROMPT_TEXT +
|
|
350
360
|
"\nIMPORTANT: Respond ONLY with a raw JSON object.",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ResolvedPRAutomation, PRStrategy, BugAction } from "../config/SelaConfig";
|
|
2
2
|
import type { HealedEvent, ProtectedEvent } from "./HealReportService";
|
|
3
|
+
import { type WorkspaceSnapshotService } from "./WorkspaceSnapshotService";
|
|
3
4
|
export interface BranchInfo {
|
|
4
5
|
branch: string | null;
|
|
5
6
|
isPR: boolean;
|
|
@@ -32,6 +33,18 @@ export interface ExecutionResult {
|
|
|
32
33
|
branchPushed: string | null;
|
|
33
34
|
errors: string[];
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Clean-Room execution lifecycle.
|
|
38
|
+
*
|
|
39
|
+
* The legacy flow committed the developer's whole dirty working tree onto
|
|
40
|
+
* the PR branch - polluting reviewers with `test.only`, commented debug
|
|
41
|
+
* blocks, etc. This refactor isolates Sela's specific AST changes onto an
|
|
42
|
+
* ephemeral branch, leaves the developer's local workspace byte-identical
|
|
43
|
+
* to its pre-Sela state, and is wrapped in a try/finally that restores
|
|
44
|
+
* the workspace even on mid-flight crashes.
|
|
45
|
+
*/
|
|
46
|
+
export declare function execute(cfg: ResolvedPRAutomation, decision: StrategyDecision, heals: HealedEvent[], branchInfo: BranchInfo, ctx: ExecuteContext,
|
|
47
|
+
/** Injectable for tests - defaults to the module singleton. */
|
|
48
|
+
workspace?: WorkspaceSnapshotService): Promise<ExecutionResult>;
|
|
36
49
|
export declare function handleBugDetected(action: BugAction, events: ProtectedEvent[], branchInfo: BranchInfo, ctx: ExecuteContext): Promise<void>;
|
|
37
50
|
//# sourceMappingURL=PRAutomationService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PRAutomationService.d.ts","sourceRoot":"","sources":["../../src/services/PRAutomationService.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACV,SAAS,EACV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"PRAutomationService.d.ts","sourceRoot":"","sources":["../../src/services/PRAutomationService.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACV,SAAS,EACV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,4BAA4B,CAAC;AAOpC,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,aAAa,GAAG,IAAI,CAAC;IAC9E;;;;OAIG;IACH,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,6EAA6E;IAC7E,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAiFD,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,UAAU,CA+EpE;AAMD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,oBAAoB,EACzB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,WAAW,EAAE,GACnB,gBAAgB,CAgElB;AAMD,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAEzC;AA6FD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,UAAU,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAE,oBAAoB,EACzB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,WAAW,EAAE,EACpB,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,cAAc;AACnB,+DAA+D;AAC/D,SAAS,GAAE,wBAAkD,GAC5D,OAAO,CAAC,eAAe,CAAC,CAkG1B;AAwTD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,cAAc,EAAE,EACxB,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CA4Gf"}
|