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

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.
@@ -1 +1 @@
1
- {"version":3,"file":"shadowRegression.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/shadowRegression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,mCAAmC,CAAC;AAe3C;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgI/D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,GAAG,gBAAgB,EAAE,CAqC9D"}
1
+ {"version":3,"file":"shadowRegression.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/shadowRegression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,mCAAmC,CAAC;AAe3C;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoI/D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,GAAG,gBAAgB,EAAE,CAqC9D"}
@@ -62,15 +62,18 @@ function registerShadowRegression(program) {
62
62
  .command("shadow-regression")
63
63
  .description("Verify a bypassed shared-locator heal against its downstream blast radius " +
64
64
  "(stateless, in-memory, zero disk mutation)")
65
- .requiredOption("--manifest <path>", "Path to sela-regression-manifest.json (emitted by the primary run)")
65
+ .option("--manifest <path>", `Path to sela-regression-manifest.json (emitted by the primary run). ` +
66
+ `Defaults to <cwd>/.sela/${RegressionManifestService_js_1.REGRESSION_MANIFEST_FILE}`)
66
67
  .option("--dir <path>", "Project dir holding sela-report.json (merge target)", process.cwd())
67
68
  .option("--config <path>", "Playwright config to pass through to the run")
68
69
  .option("--report <path>", "Override path to the base sela-report.json to merge into")
69
70
  .action(async (opts) => {
70
71
  const targetDir = path.resolve(opts.dir ?? process.cwd());
71
- const manifestAbs = path.isAbsolute(opts.manifest)
72
- ? opts.manifest
73
- : path.resolve(process.cwd(), opts.manifest);
72
+ const manifestRaw = opts.manifest ??
73
+ path.join(targetDir, ".sela", RegressionManifestService_js_1.REGRESSION_MANIFEST_FILE);
74
+ const manifestAbs = path.isAbsolute(manifestRaw)
75
+ ? manifestRaw
76
+ : path.resolve(process.cwd(), manifestRaw);
74
77
  // 1. Load + validate the manifest (throws loudly on bad input).
75
78
  let manifest;
76
79
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AA2LzE,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA+B;IACtD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAuB;IAK5C,OAAO,CAAC,MAAM,CAAC,aAAa,CAA2B;IAEvD;;;;;;;;OAQG;IACH,MAAM,CAAC,WAAW,IAAI,cAAc;IAqCpC;;;;OAIG;IACH,MAAM,CAAC,YAAY,IAAI,UAAU;IAKjC,OAAO,CAAC,MAAM,CAAC,aAAa;IAsB5B,yEAAyE;IACzE,MAAM,CAAC,SAAS,IAAI,MAAM,GAAG,IAAI;IAKjC,uDAAuD;IACvD,MAAM,CAAC,KAAK,IAAI,IAAI;CAKrB"}
1
+ {"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAiB,MAAM,cAAc,CAAC;AAgNzE,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA+B;IACtD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAuB;IAK5C,OAAO,CAAC,MAAM,CAAC,aAAa,CAA2B;IAEvD;;;;;;;;OAQG;IACH,MAAM,CAAC,WAAW,IAAI,cAAc;IAqCpC;;;;OAIG;IACH,MAAM,CAAC,YAAY,IAAI,UAAU;IAKjC,OAAO,CAAC,MAAM,CAAC,aAAa;IAsB5B,yEAAyE;IACzE,MAAM,CAAC,SAAS,IAAI,MAAM,GAAG,IAAI;IAKjC,uDAAuD;IACvD,MAAM,CAAC,KAAK,IAAI,IAAI;CAKrB"}
@@ -167,10 +167,28 @@ function loadRawConfig(configPath) {
167
167
  lastError = err;
168
168
  }
169
169
  }
170
- // Every attempt failed throw with a diagnostic instead of silently
171
- // falling back to defaults. Missing sela.config → defaults is intentional
172
- // (handled at the call site); found-but-broken is always a hard error.
173
- throw new Error(`[Sela] Failed to load ${path.basename(configPath)}: ${lastError?.message ?? "unknown error"}. ` +
170
+ // Every attempt failed. Two cases:
171
+ //
172
+ // 1. The only candidate was a .ts file and the error looks like a missing
173
+ // TypeScript loader (e.g. "Cannot find module" for a .ts import, or
174
+ // "Unknown file extension .ts"). The CLI runs in plain Node.js — no tsx/
175
+ // ts-node — so the config simply cannot be loaded here. Gracefully fall
176
+ // back to defaults rather than crashing a CLI command that doesn't need
177
+ // the config (e.g. `sela shadow-regression`).
178
+ //
179
+ // 2. Genuine config error (syntax, key validation, etc.) → hard throw so CI
180
+ // surfaces the problem instead of silently running on stale defaults.
181
+ const msg = lastError?.message ?? "";
182
+ const isNoTsLoader = configPath.endsWith(".ts") &&
183
+ (msg.includes("Cannot find module") ||
184
+ msg.includes("Unknown file extension") ||
185
+ msg.includes("ERR_UNKNOWN_FILE_EXTENSION"));
186
+ if (isNoTsLoader) {
187
+ logger_1.logger.warn(`[Sela] sela.config.ts found but no TypeScript loader is active — running on defaults. ` +
188
+ `If you need config values in the CLI, add a compiled sela.config.js alongside it.`);
189
+ return {};
190
+ }
191
+ throw new Error(`[Sela] Failed to load ${path.basename(configPath)}: ${msg || "unknown error"}. ` +
174
192
  `Ensure a TypeScript loader (Playwright, ts-node, tsx) is active, ` +
175
193
  `or provide a compiled sela.config.js alongside sela.config.ts.`);
176
194
  }
@@ -1256,7 +1256,7 @@ If the text has NOT changed, omit the "contentChange" field entirely.`;
1256
1256
  if (!this.config.regressionActive) {
1257
1257
  try {
1258
1258
  const records = RegressionManifestService_1.RegressionManifestService.buildRecords(HealReportService_1.sharedHealReport.getBypassedEvents());
1259
- const manifestPath = RegressionManifestService_1.RegressionManifestService.writeManifest(process.cwd(), records);
1259
+ const manifestPath = RegressionManifestService_1.RegressionManifestService.writeManifest(path.join(process.cwd(), ".sela"), records);
1260
1260
  if (manifestPath) {
1261
1261
  logger_1.logger.info(` Shadow-regression manifest: ${path.relative(process.cwd(), manifestPath)} ` +
1262
1262
  `(${records.length} bypass${records.length !== 1 ? "es" : ""})`);
@@ -129,6 +129,15 @@ export declare class SelaReporter implements Reporter {
129
129
  */
130
130
  private collectBypasses;
131
131
  private readBypassedEvents;
132
+ /**
133
+ * Read raw (un-prettified) BYPASSED events directly from shard files.
134
+ * Must be called BEFORE mergeShards() — the merge runs
135
+ * normalizeEventsForReport() which converts internal:role=... selector
136
+ * strings to human-readable page.getByRole(...) form. The manifest writer
137
+ * needs the raw internal strings so RegressionInjector.lookup() and
138
+ * buildLiveLocator() can consume them without a round-trip parse.
139
+ */
140
+ private readRawBypassEventsFromShards;
132
141
  private collectRunSummary;
133
142
  /**
134
143
  * Render the summary table — but only when Sela actually did something.
@@ -1 +1 @@
1
- {"version":3,"file":"SelaReporter.d.ts","sourceRoot":"","sources":["../../src/reporter/SelaReporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SelaReporter.d.ts","sourceRoot":"","sources":["../../src/reporter/SelaReporter.ts"],"names":[],"mappings":"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"}
@@ -67,6 +67,7 @@ const fs = __importStar(require("fs"));
67
67
  const path = __importStar(require("path"));
68
68
  const HealReportService_js_1 = require("../services/HealReportService.js");
69
69
  const ReportMergeService_js_1 = require("../services/ReportMergeService.js");
70
+ const RegressionManifestService_js_1 = require("../services/RegressionManifestService.js");
70
71
  const singleton_js_1 = require("../engine/singleton.js");
71
72
  const SelaError_js_1 = require("../errors/SelaError.js");
72
73
  const PendingPromptLedger_js_1 = require("../services/PendingPromptLedger.js");
@@ -223,6 +224,11 @@ class SelaReporter {
223
224
  // main-process writer, so it is the safe place to merge them into the
224
225
  // final sela-report.{html,json}. CI uses cross-machine `sela merge`.
225
226
  if (!this.isCi()) {
227
+ // Capture raw bypass events from shards BEFORE merge — the merge runs
228
+ // normalizeEventsForReport() which prettifies internal:role=... selector
229
+ // strings to page.getByRole(...) form. The manifest needs the raw
230
+ // internal strings so buildLiveLocator() can consume them directly.
231
+ const rawBypassedFromShards = this.readRawBypassEventsFromShards(this.cwd);
226
232
  try {
227
233
  this.mergeShards(this.cwd);
228
234
  }
@@ -230,6 +236,28 @@ class SelaReporter {
230
236
  const msg = err instanceof Error ? err.message : String(err);
231
237
  this.logger.error(`[Sela] shard merge failed: ${msg}`);
232
238
  }
239
+ // Write regression manifest using raw (un-prettified) bypass events.
240
+ // Fall back to readBypassedEvents() only when no shards were present
241
+ // (e.g. single-process run where reporter has in-memory events or the
242
+ // sela-report.json was pre-populated by a previous run).
243
+ try {
244
+ const bypassedEvents = rawBypassedFromShards.length > 0
245
+ ? rawBypassedFromShards
246
+ : this.readBypassedEvents();
247
+ if (bypassedEvents.length > 0) {
248
+ const records = RegressionManifestService_js_1.RegressionManifestService.buildRecords(bypassedEvents);
249
+ const manifestPath = RegressionManifestService_js_1.RegressionManifestService.writeManifest(path.join(this.cwd, ".sela"), records);
250
+ if (manifestPath) {
251
+ this.logger.info(` Shadow-regression manifest: ${path.relative(this.cwd, manifestPath)} ` +
252
+ `(${records.length} bypass${records.length !== 1 ? "es" : ""})`);
253
+ this.logger.info(" Verify with: npx sela shadow-regression");
254
+ }
255
+ }
256
+ }
257
+ catch (err) {
258
+ const msg = err instanceof Error ? err.message : String(err);
259
+ this.logger.error(`[Sela] regression manifest write failed: ${msg}`);
260
+ }
233
261
  }
234
262
  // ── CI: centralized git/PR flow ──────────────────────────────
235
263
  //
@@ -341,6 +369,40 @@ class SelaReporter {
341
369
  return [];
342
370
  }
343
371
  }
372
+ /**
373
+ * Read raw (un-prettified) BYPASSED events directly from shard files.
374
+ * Must be called BEFORE mergeShards() — the merge runs
375
+ * normalizeEventsForReport() which converts internal:role=... selector
376
+ * strings to human-readable page.getByRole(...) form. The manifest writer
377
+ * needs the raw internal strings so RegressionInjector.lookup() and
378
+ * buildLiveLocator() can consume them without a round-trip parse.
379
+ */
380
+ readRawBypassEventsFromShards(cwd) {
381
+ const shardFiles = ReportMergeService_js_1.ReportMergeService.discoverShardFiles((0, HealReportService_js_1.reportShardDir)(cwd), "sela-shard-*.json");
382
+ if (shardFiles.length === 0)
383
+ return [];
384
+ const seen = new Set();
385
+ const result = [];
386
+ for (const file of shardFiles) {
387
+ try {
388
+ const events = ReportMergeService_js_1.ReportMergeService.readShardEvents(file);
389
+ for (const e of events) {
390
+ if (e.kind !== "BYPASSED")
391
+ continue;
392
+ const dedup = e.deterministicKey ?? e.stableId ?? "";
393
+ if (dedup && seen.has(dedup))
394
+ continue;
395
+ if (dedup)
396
+ seen.add(dedup);
397
+ result.push(e);
398
+ }
399
+ }
400
+ catch {
401
+ // Individual shard failures are non-fatal — merge() already logs them.
402
+ }
403
+ }
404
+ return result;
405
+ }
344
406
  collectRunSummary() {
345
407
  const healed = this.report.getHealedEvents().length;
346
408
  const held = this.report.getProtectedEvents().length;
@@ -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;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"}
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;CA0B3E"}
@@ -172,18 +172,31 @@ class RegressionInjector {
172
172
  */
173
173
  lookup(filePath, line, oldSelector) {
174
174
  const f = normalizePath(filePath).toLowerCase();
175
- const candidates = this.records.filter((r) => {
175
+ // Primary: match on line + file (precise call-site).
176
+ const lineCandidates = this.records.filter((r) => {
176
177
  if (r.failureLine !== line)
177
178
  return false;
178
179
  const rf = normalizePath(r.sourceFile).toLowerCase();
179
180
  return f === rf || f.endsWith(rf) || rf.endsWith(f);
180
181
  });
181
- if (candidates.length === 0)
182
- return null;
183
- const exact = candidates.find((r) => r.oldSelector === oldSelector);
184
- if (exact)
185
- return exact.healedSelector;
186
- return candidates.length === 1 ? candidates[0].healedSelector : null;
182
+ if (lineCandidates.length > 0) {
183
+ const exact = lineCandidates.find((r) => r.oldSelector === oldSelector);
184
+ if (exact)
185
+ return exact.healedSelector;
186
+ if (lineCandidates.length === 1)
187
+ return lineCandidates[0].healedSelector;
188
+ }
189
+ // Fallback: shared locators — multiple tests in the same file fail at
190
+ // different lines but share the same broken selector. The manifest stores
191
+ // failureLine from the FIRST failure only, so subsequent tests miss the
192
+ // line match. Widen to selector + file so every caller gets injected.
193
+ const selectorMatch = this.records.find((r) => {
194
+ if (r.oldSelector !== oldSelector)
195
+ return false;
196
+ const rf = normalizePath(r.sourceFile).toLowerCase();
197
+ return f === rf || f.endsWith(rf) || rf.endsWith(f);
198
+ });
199
+ return selectorMatch?.healedSelector ?? null;
187
200
  }
188
201
  }
189
202
  exports.RegressionInjector = RegressionInjector;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sela-core",
3
- "version": "0.1.0-alpha.37",
3
+ "version": "0.1.0-alpha.39",
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",