@vijaypjavvadi/bdd2pw 3.9.0 → 3.10.0

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/CHANGELOG.md CHANGED
@@ -9,6 +9,96 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  _Nothing yet._
11
11
 
12
+ ## [3.10.0] — 2026-06-06
13
+
14
+ ### Added — self-healing stats sidecar + `bdd2pw heal-stats` CLI
15
+
16
+ v1.1+ has shipped a runtime `healOrThrow` helper that emits
17
+ `register` / `heal_attempt` / `healed` / `heal_unavailable` events
18
+ to `<repo>/artefacts/heal-events.jsonl`. Until now those events
19
+ sat in a JSONL file with no offline analyzer — operators had to
20
+ grep the file themselves to see if healing was working.
21
+
22
+ v3.10.0 adds:
23
+
24
+ **1. `bdd2pw heal-stats <repo>` CLI** — reads
25
+ `<repo>/artefacts/heal-events.jsonl` and writes
26
+ `<repo>/artefacts/heal-stats.json` with:
27
+
28
+ {
29
+ "version": "3.10.0",
30
+ "generatedAt": "2026-06-06T...",
31
+ "source": "<events file>",
32
+ "totals": {
33
+ "registrations": 47,
34
+ "healAttempts": 6,
35
+ "healed": 4,
36
+ "healUnavailable": 2,
37
+ "healRate": 0.6667,
38
+ "uniqueFields": 23,
39
+ "uniquePages": 3
40
+ },
41
+ "topFailingFields": [
42
+ { "page": "LoginPage", "name": "submitButton",
43
+ "attempts": 3, "healed": 2 },
44
+ ...
45
+ ],
46
+ "topErrors": [
47
+ { "error": "timeout <n>ms exceeded", "count": 4 },
48
+ ...
49
+ ],
50
+ "topCandidates": [
51
+ { "selector": "[data-testid='submit']", "promotions": 2,
52
+ "averageConfidence": 0.87 },
53
+ ...
54
+ ],
55
+ "retryLatencyMs": { "p50": 1240, "p95": 3010,
56
+ "min": 880, "max": 3010 },
57
+ "perScenario": [
58
+ { "scenario": "User can log in", "attempts": 1, "healed": 1 },
59
+ ...
60
+ ]
61
+ }
62
+
63
+ Where v3.9.0's `llm-stats.json` measures the LLM batching ROI per
64
+ scaffold, v3.10.0's `heal-stats.json` measures the self-healing
65
+ ROI per TEST RUN.
66
+
67
+ **2. New module `src/reports/healStats.ts`** — pure
68
+ `aggregate(events, source, topN)` function plus the wrapper
69
+ `analyseHealStats(opts)` that resolves the input path
70
+ (file / repo-dir / artefacts-subdir) and writes the sidecar.
71
+
72
+ **3. Error normalisation.** The aggregator collapses error messages
73
+ into stable buckets (lowercase, strip "Error:"/"TimeoutError:"
74
+ prefixes, replace runs of 3+ digits with `<n>`) so transient
75
+ timestamps / IDs don't fragment the histogram.
76
+
77
+ **4. Retry latency derivation.** Pairs each `heal_attempt` with its
78
+ matching `healed` (by `page+name+method`) and reports the timestamp
79
+ delta as the retry latency. Computes p50 / p95 / min / max across
80
+ the run.
81
+
82
+ **5. Graceful empty-input behaviour.** Pointing the CLI at a repo
83
+ with no heal-events.jsonl writes a zero-event summary instead of
84
+ failing — `bdd2pw heal-stats` is now safe to run unconditionally
85
+ in CI after `npx playwright test`.
86
+
87
+ ### Tests
88
+
89
+ `tests/unit/v3100HealStats.test.ts`:
90
+ - Empty input → all-zero summary.
91
+ - Mixed register / heal_attempt / healed / heal_unavailable sequence
92
+ aggregates correctly (counts, healRate, topFailingFields,
93
+ topErrors, topCandidates, p50/p95 latency, per-scenario rollup).
94
+ - `topN` honored — top-3 returns 3 entries from 5 distinct fields.
95
+ - End-to-end: write JSONL → `analyseHealStats(file)` → read JSON
96
+ back and verify shape + version stamp.
97
+ - Missing-file safety: pointing at a directory with no
98
+ heal-events.jsonl returns total=0 and writes an empty summary.
99
+ - Repo-path resolution: passing a directory finds
100
+ `artefacts/heal-events.jsonl` automatically.
101
+
12
102
  ## [3.9.0] — 2026-06-05
13
103
 
14
104
  ### Added — opt-in LLM telemetry sidecar
package/dist/cli.js CHANGED
@@ -42,6 +42,7 @@ const commander_1 = require("commander");
42
42
  const path = __importStar(require("path"));
43
43
  const index_1 = require("./index");
44
44
  const llm_1 = require("./llm");
45
+ const healStats_1 = require("./reports/healStats");
45
46
  const logger_1 = require("./utils/logger");
46
47
  const program = new commander_1.Command();
47
48
  program
@@ -75,6 +76,7 @@ program
75
76
  .option("--telemetry", "Enable local SQLite failure telemetry", false)
76
77
  .option("--force", "Overwrite existing spec files", false)
77
78
  .option("--self-healing", "Wrap emitted locators in healOrThrow() and generate lib/heal.ts + tsconfig path alias. Locator events are logged to artefacts/heal-events.jsonl for the offline self-heal pipeline. Action-time healing is v1.2.", false)
79
+ .option("--llm-stats", "v3.9.0 — write <repo>/artefacts/llm-stats.json with per-call latency, token counts, cache hit rate, and estimated cost.", false)
78
80
  .action(async (feature, opts) => {
79
81
  try {
80
82
  // v2.0 — wire the actual LLM config when --llm is passed. The legacy
@@ -122,6 +124,8 @@ program
122
124
  // Commander negates --no-discovery into opts.discovery=false
123
125
  noDiscovery: opts.discovery === false,
124
126
  selfHealing: opts.selfHealing,
127
+ // v3.9.0 — telemetry sidecar
128
+ llmStats: opts.llmStats === true,
125
129
  });
126
130
  logger_1.logger.info({ result }, "scaffold complete");
127
131
  }
@@ -235,6 +239,32 @@ program
235
239
  process.stdout.write(`\n${result.proposalsWritten} proposal(s) written to ${result.outputPath} ` +
236
240
  `(from ${result.totalCandidates} candidate entries).\n`);
237
241
  });
242
+ /**
243
+ * v3.10.0 — heal-stats subcommand. Reads `<repo>/artefacts/heal-events.jsonl`
244
+ * (produced by the runtime `healOrThrow` helper) and writes
245
+ * `<repo>/artefacts/heal-stats.json` summarising heal attempts,
246
+ * success rate, top failing fields, top error patterns, retry latency,
247
+ * and the candidate selectors that got promoted. Run after
248
+ * `npx playwright test` in CI to track self-healing ROI per test run.
249
+ */
250
+ program
251
+ .command("heal-stats")
252
+ .description("Aggregate <repo>/artefacts/heal-events.jsonl into a heal-stats.json sidecar.")
253
+ .argument("<input>", "Path to heal-events.jsonl OR the test repo containing artefacts/heal-events.jsonl")
254
+ .option("--out <path>", "Where to write heal-stats.json. Defaults to next to the events file.")
255
+ .option("--top <n>", "How many entries to keep in each ranked list (failing fields, errors, candidates, scenarios). Default 10.", "10")
256
+ .action(async (input, raw) => {
257
+ const result = await (0, healStats_1.analyseHealStats)({
258
+ inputPath: input,
259
+ outputPath: raw.out,
260
+ topN: raw.top ? Number(raw.top) : undefined,
261
+ });
262
+ logger_1.logger.info({
263
+ outputPath: result.outputPath,
264
+ totalEvents: result.totalEvents,
265
+ }, "heal-stats: complete");
266
+ process.stdout.write(`\nheal-stats: wrote ${result.outputPath} (parsed ${result.totalEvents} event(s)).\n`);
267
+ });
238
268
  program.parseAsync(process.argv).catch((err) => {
239
269
  logger_1.logger.error({ err }, "fatal");
240
270
  process.exit(1);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * v3.10.0 — heal-events.jsonl → heal-stats.json analyzer.
3
+ *
4
+ * Same flavor as v3.9.0's `LLMTelemetry` sidecar but for the
5
+ * self-healing pipeline. Where v3.9.0 measures the LLM batching ROI
6
+ * per scaffold, v3.10.0 measures the self-healing ROI per TEST RUN.
7
+ *
8
+ * Input: `<repo>/artefacts/heal-events.jsonl` — one JSON event per
9
+ * line, written by the runtime `healOrThrow` helper from
10
+ * `templates/heal.ts.tmpl`. Event kinds:
11
+ * - `register` — locator constructed
12
+ * - `heal_attempt` — action failed; asking the heal
13
+ * service for a candidate
14
+ * - `healed` — candidate worked; subsequent
15
+ * calls use it transparently
16
+ * - `heal_unavailable` — no candidate / candidate failed
17
+ *
18
+ * Output: `<repo>/artefacts/heal-stats.json` — stable shape:
19
+ *
20
+ * {
21
+ * "version": "3.10.0",
22
+ * "generatedAt": "2026-...",
23
+ * "source": "<events file>",
24
+ * "totals": {
25
+ * "registrations": 47,
26
+ * "healAttempts": 6,
27
+ * "healed": 4,
28
+ * "healUnavailable": 2,
29
+ * "healRate": 0.6667, // healed / healAttempts
30
+ * "uniqueFields": 23,
31
+ * "uniquePages": 3
32
+ * },
33
+ * "topFailingFields": [
34
+ * { "page": "LoginPage", "name": "submitButton", "attempts": 3, "healed": 2 },
35
+ * ...
36
+ * ],
37
+ * "topErrors": [
38
+ * { "error": "Timeout 30000ms exceeded", "count": 4 },
39
+ * ...
40
+ * ],
41
+ * "topCandidates": [
42
+ * { "selector": "[data-testid='submit']", "promotions": 2,
43
+ * "averageConfidence": 0.87 },
44
+ * ...
45
+ * ],
46
+ * "retryLatencyMs": { "p50": 1240, "p95": 3010, "min": 880, "max": 3010 },
47
+ * "perScenario": [
48
+ * { "scenario": "User can log in", "attempts": 1, "healed": 1 },
49
+ * ...
50
+ * ]
51
+ * }
52
+ *
53
+ * Why a separate command (not part of scaffold): scaffold GENERATES the
54
+ * test repo; the heal events are produced when the user RUNS the
55
+ * generated tests. So this analyzer is a post-test command, run from
56
+ * CI after `npx playwright test`. Same pattern as `bdd2pw propose-rules`
57
+ * which runs after the LLM has populated `candidate-rules.jsonl`.
58
+ */
59
+ export interface HealStatsOptions {
60
+ /** Path to heal-events.jsonl OR a repo dir containing it. */
61
+ inputPath: string;
62
+ /** Override output path. Default: <input dir>/heal-stats.json. */
63
+ outputPath?: string;
64
+ /** How many top entries to keep in each ranked list. Default 10. */
65
+ topN?: number;
66
+ }
67
+ export interface HealStatsResult {
68
+ outputPath: string;
69
+ totalEvents: number;
70
+ }
71
+ /** One event line in heal-events.jsonl. Shape tracks `templates/heal.ts.tmpl`. */
72
+ interface HealEvent {
73
+ ts: string;
74
+ event: "register" | "heal_attempt" | "healed" | "heal_unavailable";
75
+ page: string;
76
+ name: string;
77
+ scenario_name?: string | null;
78
+ method?: string;
79
+ original?: string | null;
80
+ healed?: string | null;
81
+ confidence?: number | null;
82
+ error?: string | null;
83
+ }
84
+ export interface HealStats {
85
+ version: string;
86
+ generatedAt: string;
87
+ source: string;
88
+ totals: {
89
+ registrations: number;
90
+ healAttempts: number;
91
+ healed: number;
92
+ healUnavailable: number;
93
+ healRate: number;
94
+ uniqueFields: number;
95
+ uniquePages: number;
96
+ };
97
+ topFailingFields: {
98
+ page: string;
99
+ name: string;
100
+ attempts: number;
101
+ healed: number;
102
+ }[];
103
+ topErrors: {
104
+ error: string;
105
+ count: number;
106
+ }[];
107
+ topCandidates: {
108
+ selector: string;
109
+ promotions: number;
110
+ averageConfidence: number | null;
111
+ }[];
112
+ retryLatencyMs: {
113
+ p50: number;
114
+ p95: number;
115
+ min: number;
116
+ max: number;
117
+ };
118
+ perScenario: {
119
+ scenario: string;
120
+ attempts: number;
121
+ healed: number;
122
+ }[];
123
+ }
124
+ /** Public entry point. */
125
+ export declare function analyseHealStats(opts: HealStatsOptions): Promise<HealStatsResult>;
126
+ /**
127
+ * Compute a HealStats summary from an in-memory event list. Pure
128
+ * function — no I/O. Used both by the public CLI entry and the unit
129
+ * tests.
130
+ */
131
+ export declare function aggregate(events: HealEvent[], source: string, topN: number): HealStats;
132
+ export {};
@@ -0,0 +1,303 @@
1
+ "use strict";
2
+ /**
3
+ * v3.10.0 — heal-events.jsonl → heal-stats.json analyzer.
4
+ *
5
+ * Same flavor as v3.9.0's `LLMTelemetry` sidecar but for the
6
+ * self-healing pipeline. Where v3.9.0 measures the LLM batching ROI
7
+ * per scaffold, v3.10.0 measures the self-healing ROI per TEST RUN.
8
+ *
9
+ * Input: `<repo>/artefacts/heal-events.jsonl` — one JSON event per
10
+ * line, written by the runtime `healOrThrow` helper from
11
+ * `templates/heal.ts.tmpl`. Event kinds:
12
+ * - `register` — locator constructed
13
+ * - `heal_attempt` — action failed; asking the heal
14
+ * service for a candidate
15
+ * - `healed` — candidate worked; subsequent
16
+ * calls use it transparently
17
+ * - `heal_unavailable` — no candidate / candidate failed
18
+ *
19
+ * Output: `<repo>/artefacts/heal-stats.json` — stable shape:
20
+ *
21
+ * {
22
+ * "version": "3.10.0",
23
+ * "generatedAt": "2026-...",
24
+ * "source": "<events file>",
25
+ * "totals": {
26
+ * "registrations": 47,
27
+ * "healAttempts": 6,
28
+ * "healed": 4,
29
+ * "healUnavailable": 2,
30
+ * "healRate": 0.6667, // healed / healAttempts
31
+ * "uniqueFields": 23,
32
+ * "uniquePages": 3
33
+ * },
34
+ * "topFailingFields": [
35
+ * { "page": "LoginPage", "name": "submitButton", "attempts": 3, "healed": 2 },
36
+ * ...
37
+ * ],
38
+ * "topErrors": [
39
+ * { "error": "Timeout 30000ms exceeded", "count": 4 },
40
+ * ...
41
+ * ],
42
+ * "topCandidates": [
43
+ * { "selector": "[data-testid='submit']", "promotions": 2,
44
+ * "averageConfidence": 0.87 },
45
+ * ...
46
+ * ],
47
+ * "retryLatencyMs": { "p50": 1240, "p95": 3010, "min": 880, "max": 3010 },
48
+ * "perScenario": [
49
+ * { "scenario": "User can log in", "attempts": 1, "healed": 1 },
50
+ * ...
51
+ * ]
52
+ * }
53
+ *
54
+ * Why a separate command (not part of scaffold): scaffold GENERATES the
55
+ * test repo; the heal events are produced when the user RUNS the
56
+ * generated tests. So this analyzer is a post-test command, run from
57
+ * CI after `npx playwright test`. Same pattern as `bdd2pw propose-rules`
58
+ * which runs after the LLM has populated `candidate-rules.jsonl`.
59
+ */
60
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
61
+ if (k2 === undefined) k2 = k;
62
+ var desc = Object.getOwnPropertyDescriptor(m, k);
63
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
64
+ desc = { enumerable: true, get: function() { return m[k]; } };
65
+ }
66
+ Object.defineProperty(o, k2, desc);
67
+ }) : (function(o, m, k, k2) {
68
+ if (k2 === undefined) k2 = k;
69
+ o[k2] = m[k];
70
+ }));
71
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
72
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
73
+ }) : function(o, v) {
74
+ o["default"] = v;
75
+ });
76
+ var __importStar = (this && this.__importStar) || (function () {
77
+ var ownKeys = function(o) {
78
+ ownKeys = Object.getOwnPropertyNames || function (o) {
79
+ var ar = [];
80
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
81
+ return ar;
82
+ };
83
+ return ownKeys(o);
84
+ };
85
+ return function (mod) {
86
+ if (mod && mod.__esModule) return mod;
87
+ var result = {};
88
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
89
+ __setModuleDefault(result, mod);
90
+ return result;
91
+ };
92
+ })();
93
+ Object.defineProperty(exports, "__esModule", { value: true });
94
+ exports.analyseHealStats = analyseHealStats;
95
+ exports.aggregate = aggregate;
96
+ const fs = __importStar(require("fs-extra"));
97
+ const path = __importStar(require("path"));
98
+ const PACKAGE_VERSION = "3.10.0";
99
+ /** Public entry point. */
100
+ async function analyseHealStats(opts) {
101
+ const jsonlPath = await resolveJsonlPath(opts.inputPath);
102
+ const events = await readEvents(jsonlPath);
103
+ const summary = aggregate(events, jsonlPath, opts.topN ?? 10);
104
+ const outputPath = opts.outputPath ?? path.join(path.dirname(jsonlPath), "heal-stats.json");
105
+ await fs.ensureDir(path.dirname(outputPath));
106
+ await fs.writeFile(outputPath, JSON.stringify(summary, null, 2), "utf8");
107
+ return { outputPath, totalEvents: events.length };
108
+ }
109
+ /* ─── pure aggregation (testable without fs) ──────────────────────── */
110
+ /**
111
+ * Compute a HealStats summary from an in-memory event list. Pure
112
+ * function — no I/O. Used both by the public CLI entry and the unit
113
+ * tests.
114
+ */
115
+ function aggregate(events, source, topN) {
116
+ const fieldKey = (e) => `${e.page}::${e.name}`;
117
+ const fieldAttempts = new Map();
118
+ const errorCounts = new Map();
119
+ const candidateStats = new Map();
120
+ const scenarioStats = new Map();
121
+ const uniquePages = new Set();
122
+ const uniqueFields = new Set();
123
+ const retryLatencies = [];
124
+ /**
125
+ * Match heal_attempt events with their matching `healed` /
126
+ * `heal_unavailable` outcome by (page, name, method). The keying
127
+ * assumes a heal attempt resolves before another one fires for the
128
+ * same field+method combo, which holds in practice — actions run
129
+ * serially per test.
130
+ */
131
+ const openAttempts = new Map();
132
+ const attemptKey = (e) => `${e.page}::${e.name}::${e.method ?? ""}`;
133
+ let registrations = 0;
134
+ let healAttempts = 0;
135
+ let healed = 0;
136
+ let healUnavailable = 0;
137
+ for (const e of events) {
138
+ uniquePages.add(e.page);
139
+ uniqueFields.add(fieldKey(e));
140
+ if (e.event === "register") {
141
+ registrations += 1;
142
+ continue;
143
+ }
144
+ if (e.event === "heal_attempt") {
145
+ healAttempts += 1;
146
+ const field = fieldAttempts.get(fieldKey(e)) ?? {
147
+ page: e.page,
148
+ name: e.name,
149
+ attempts: 0,
150
+ healed: 0,
151
+ };
152
+ field.attempts += 1;
153
+ fieldAttempts.set(fieldKey(e), field);
154
+ if (e.error) {
155
+ const msg = truncateError(e.error);
156
+ errorCounts.set(msg, (errorCounts.get(msg) ?? 0) + 1);
157
+ }
158
+ const scenario = e.scenario_name ?? "(no scenario context)";
159
+ const ss = scenarioStats.get(scenario) ?? { attempts: 0, healed: 0 };
160
+ ss.attempts += 1;
161
+ scenarioStats.set(scenario, ss);
162
+ openAttempts.set(attemptKey(e), Date.parse(e.ts));
163
+ continue;
164
+ }
165
+ if (e.event === "healed") {
166
+ healed += 1;
167
+ const field = fieldAttempts.get(fieldKey(e)) ?? {
168
+ page: e.page,
169
+ name: e.name,
170
+ attempts: 0,
171
+ healed: 0,
172
+ };
173
+ field.healed += 1;
174
+ fieldAttempts.set(fieldKey(e), field);
175
+ if (e.healed) {
176
+ const cs = candidateStats.get(e.healed) ?? {
177
+ promotions: 0,
178
+ confidenceSum: 0,
179
+ confidenceCount: 0,
180
+ };
181
+ cs.promotions += 1;
182
+ if (typeof e.confidence === "number") {
183
+ cs.confidenceSum += e.confidence;
184
+ cs.confidenceCount += 1;
185
+ }
186
+ candidateStats.set(e.healed, cs);
187
+ }
188
+ const scenario = e.scenario_name ?? "(no scenario context)";
189
+ const ss = scenarioStats.get(scenario) ?? { attempts: 0, healed: 0 };
190
+ ss.healed += 1;
191
+ scenarioStats.set(scenario, ss);
192
+ const startTs = openAttempts.get(attemptKey(e));
193
+ if (startTs !== undefined) {
194
+ retryLatencies.push(Date.parse(e.ts) - startTs);
195
+ openAttempts.delete(attemptKey(e));
196
+ }
197
+ continue;
198
+ }
199
+ if (e.event === "heal_unavailable") {
200
+ healUnavailable += 1;
201
+ openAttempts.delete(attemptKey(e));
202
+ continue;
203
+ }
204
+ }
205
+ const sortedFailingFields = Array.from(fieldAttempts.values())
206
+ .sort((a, b) => b.attempts - a.attempts)
207
+ .slice(0, topN);
208
+ const sortedErrors = Array.from(errorCounts.entries())
209
+ .map(([error, count]) => ({ error, count }))
210
+ .sort((a, b) => b.count - a.count)
211
+ .slice(0, topN);
212
+ const sortedCandidates = Array.from(candidateStats.entries())
213
+ .map(([selector, s]) => ({
214
+ selector,
215
+ promotions: s.promotions,
216
+ averageConfidence: s.confidenceCount > 0 ? s.confidenceSum / s.confidenceCount : null,
217
+ }))
218
+ .sort((a, b) => b.promotions - a.promotions)
219
+ .slice(0, topN);
220
+ const sortedScenarios = Array.from(scenarioStats.entries())
221
+ .map(([scenario, s]) => ({ scenario, ...s }))
222
+ .sort((a, b) => b.attempts - a.attempts)
223
+ .slice(0, topN);
224
+ const latenciesSorted = [...retryLatencies].sort((a, b) => a - b);
225
+ return {
226
+ version: PACKAGE_VERSION,
227
+ generatedAt: new Date().toISOString(),
228
+ source,
229
+ totals: {
230
+ registrations,
231
+ healAttempts,
232
+ healed,
233
+ healUnavailable,
234
+ healRate: healAttempts === 0 ? 0 : healed / healAttempts,
235
+ uniqueFields: uniqueFields.size,
236
+ uniquePages: uniquePages.size,
237
+ },
238
+ topFailingFields: sortedFailingFields,
239
+ topErrors: sortedErrors,
240
+ topCandidates: sortedCandidates,
241
+ retryLatencyMs: {
242
+ p50: percentile(latenciesSorted, 0.5),
243
+ p95: percentile(latenciesSorted, 0.95),
244
+ min: latenciesSorted.length ? latenciesSorted[0] : 0,
245
+ max: latenciesSorted.length
246
+ ? latenciesSorted[latenciesSorted.length - 1]
247
+ : 0,
248
+ },
249
+ perScenario: sortedScenarios,
250
+ };
251
+ }
252
+ function percentile(sortedAsc, p) {
253
+ if (sortedAsc.length === 0)
254
+ return 0;
255
+ const idx = Math.ceil(sortedAsc.length * p) - 1;
256
+ return sortedAsc[Math.max(0, Math.min(idx, sortedAsc.length - 1))];
257
+ }
258
+ /**
259
+ * Normalise an error message so different timestamps / IDs collapse to
260
+ * the same bucket: lowercase, strip leading "Error: " / "TimeoutError",
261
+ * collapse runs of digits.
262
+ */
263
+ function truncateError(s) {
264
+ return s
265
+ .toLowerCase()
266
+ .replace(/^(?:error|timeouterror|protocolerror):\s*/i, "")
267
+ .replace(/\b\d{3,}\b/g, "<n>")
268
+ .slice(0, 120);
269
+ }
270
+ /* ─── filesystem glue ─────────────────────────────────────────────── */
271
+ async function resolveJsonlPath(inputPath) {
272
+ const stat = await fs.stat(inputPath).catch(() => undefined);
273
+ if (stat?.isFile())
274
+ return inputPath;
275
+ if (stat?.isDirectory()) {
276
+ const direct = path.join(inputPath, "heal-events.jsonl");
277
+ if (await fs.pathExists(direct))
278
+ return direct;
279
+ const nested = path.join(inputPath, "artefacts", "heal-events.jsonl");
280
+ if (await fs.pathExists(nested))
281
+ return nested;
282
+ return nested; // analyser will handle 'no events' gracefully
283
+ }
284
+ return path.join(inputPath, "artefacts", "heal-events.jsonl");
285
+ }
286
+ async function readEvents(jsonlPath) {
287
+ if (!(await fs.pathExists(jsonlPath)))
288
+ return [];
289
+ const raw = await fs.readFile(jsonlPath, "utf8");
290
+ const out = [];
291
+ for (const line of raw.split(/\r?\n/)) {
292
+ if (!line.trim())
293
+ continue;
294
+ try {
295
+ out.push(JSON.parse(line));
296
+ }
297
+ catch {
298
+ /* skip malformed line */
299
+ }
300
+ }
301
+ return out;
302
+ }
303
+ //# sourceMappingURL=healStats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"healStats.js","sourceRoot":"","sources":["../../src/reports/healStats.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vijaypjavvadi/bdd2pw",
3
- "version": "3.9.0",
3
+ "version": "3.10.0",
4
4
  "description": "Scaffold runnable Playwright TypeScript tests from Gherkin .feature files. Detects existing Page Objects, scans live pages via Microsoft Playwright MCP, emits POMs + specs, ready for execution. CLI + HTTP service. Optional governed LLM fallback (Anthropic / OpenAI / Gemini).",
5
5
  "bin": {
6
6
  "bdd2pw": "dist/cli.js"