@vijaypjavvadi/bdd2pw 3.9.0 → 3.12.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,251 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  _Nothing yet._
11
11
 
12
+ ## [3.12.0] — 2026-06-19
13
+
14
+ > Note: v3.11.0 was tagged in git but never published to npm. v3.12.0
15
+ > on npm is the first release that includes BOTH the v3.11.0 OpenAI
16
+ > provider AND the v3.12.0 Gemini provider. Anyone who installs
17
+ > `@vijaypjavvadi/bdd2pw@latest` after this release gets all three
18
+ > providers (Anthropic, OpenAI, Gemini) with full parity in one go.
19
+
20
+ ### Added — Gemini provider, three-provider parity is complete
21
+
22
+ `LLMClientOptions.provider` now accepts `"gemini"` alongside
23
+ `"anthropic"` and `"openai"`. `createLLMClient` factory routes
24
+ `"gemini"` to a new `GeminiLLMClient` that matches the surface
25
+ area of the other two:
26
+
27
+ - Single-step `generateBinding(input)`
28
+ - Batched `generateBatchBindings(inputs[])` — same per-step cache
29
+ lookup + one batched prompt as the v3.5.0 Anthropic batching
30
+ - Cache hit accounting (`callsMade`, `callsAttempted`,
31
+ `cacheBackendPersistent`, `cacheBackendFallbackReason`)
32
+ - Budget enforcement via `maxCalls`
33
+ - Governance sanitisation through the same sidecar (fail-closed
34
+ if the sidecar is unreachable — identical to Anthropic/OpenAI)
35
+ - Provider timeout enforcement — Gemini's SDK has no native
36
+ timeout option, so we wrap the call in a `Promise.race` against
37
+ `setTimeout`; surfaces a clear `Gemini call exceeded Xms timeout`
38
+ error in logs and the result `error` field
39
+ - LLMLogEvent stream that feeds the v3.9.0 telemetry sidecar
40
+
41
+ ### Default model: `gemini-2.5-flash`
42
+
43
+ For bdd2pw's structured-JSON task, Flash is the price/perf sweet
44
+ spot. Pricing snapshot: $0.10 per million input tokens, $0.40 per
45
+ million output. That is the cheapest model across all three
46
+ providers — cheaper than `gpt-4o-mini` ($0.15) and dramatically
47
+ cheaper than `claude-sonnet-4-6` ($3.00). Override via
48
+ `LLMClientOptions.model` or `--llm-model`.
49
+
50
+ ### Pricing rows added to `DEFAULT_PRICING`
51
+
52
+ `telemetry.ts` now includes pricing snapshots for: `gemini-2.5-flash`,
53
+ `gemini-2.5-pro`, `gemini-2.0-flash`, `gemini-1.5-flash`,
54
+ `gemini-1.5-pro`. v3.9.0 `llm-stats.json` cost estimates work
55
+ end-to-end for Gemini runs.
56
+
57
+ ### CLI
58
+
59
+ `bdd2pw scaffold ... --llm gemini` now works. `--llm-model` help
60
+ text updated to list all three provider defaults.
61
+
62
+ ### Auth env vars
63
+
64
+ Reads `GEMINI_API_KEY` first, then falls back to `GOOGLE_API_KEY`
65
+ (both are widely used in the Google AI Studio + Vertex ecosystem).
66
+
67
+ ### `optionalDependencies`
68
+
69
+ `@google/generative-ai ^0.21.0` added alongside `@anthropic-ai/sdk`
70
+ and `openai`. Same defensive `require()` loading pattern — teams
71
+ that only use Anthropic do not need to install the Gemini SDK,
72
+ and vice versa. Missing-package error message points to
73
+ `npm install @google/generative-ai`.
74
+
75
+ ### Cache compat
76
+
77
+ Cache keys include the model name (since v2.0), so a scaffold
78
+ cached under `claude-sonnet-4-6` does NOT hit the cache when re-run
79
+ under `gemini-2.5-flash` — you get a fresh provider call. Within
80
+ the same model, cache hits work identically regardless of how many
81
+ times you switch providers across scaffold runs.
82
+
83
+ ### Tests
84
+
85
+ `tests/unit/v3120Gemini.test.ts`:
86
+ - Default model + DEFAULT_PRICING lookup.
87
+ - generateBinding succeeds with a well-formed JSON response.
88
+ - generateBatchBindings produces N bindings from ONE provider call
89
+ (cache misses → single batched prompt → JSON array → N bindings).
90
+ - Budget exhaustion returns an error without making a provider call.
91
+ - Missing API key short-circuits before the SDK loads.
92
+ - Malformed JSON response surfaces a parse error.
93
+ - Provider timeout aborts a hung call (Promise.race against
94
+ setTimeout works as designed).
95
+
96
+ ## [3.11.0] — 2026-06-08
97
+
98
+ ### Added — OpenAI provider parity
99
+
100
+ `LLMClientOptions.provider` now accepts `"openai"` alongside
101
+ `"anthropic"`. The factory wires up `OpenAILLMClient` which matches
102
+ the Anthropic client's surface area completely:
103
+
104
+ - Single-step `generateBinding(input)`
105
+ - Batched `generateBatchBindings(inputs[])` — same per-step cache
106
+ lookup + one batched prompt as v3.5.0 batching
107
+ - Cache hit accounting (`callsMade`, `callsAttempted`,
108
+ `cacheBackendPersistent`, `cacheBackendFallbackReason`)
109
+ - Budget enforcement via `maxCalls`
110
+ - Governance sanitisation through the same sidecar
111
+ - Step deadlines + provider timeouts
112
+ - LLMLogEvent stream that feeds the v3.9.0 telemetry sidecar
113
+
114
+ What differs is purely the SDK call shape — OpenAI's
115
+ `chat.completions.create()` instead of Anthropic's `messages.create()`,
116
+ and the response unpacking (`choices[0].message.content` vs
117
+ `content[0].text`, `usage.prompt_tokens` vs `usage.input_tokens`).
118
+
119
+ ### Default model: `gpt-4o-mini`
120
+
121
+ bdd2pw's task is structured JSON output over regex-shaped
122
+ deterministic patterns. Mini handles it reliably and runs ~17x
123
+ cheaper than gpt-4o ($0.15 vs $2.50 per million input tokens).
124
+ Override via `LLMClientOptions.model` or `--llm-model`.
125
+
126
+ ### Pricing rows added to `DEFAULT_PRICING`
127
+
128
+ `telemetry.ts` now includes pricing snapshots for: `gpt-4o`,
129
+ `gpt-4o-mini`, `gpt-4-turbo`, `o1`, `o1-mini`, `o1-preview`. v3.9.0
130
+ `llm-stats.json` cost estimates work end-to-end for OpenAI runs.
131
+ Prices are Q4 2025 published rates; override via
132
+ `new LLMTelemetry(scaffoldId, version, pricingOverride)` if you
133
+ have negotiated rates.
134
+
135
+ ### CLI
136
+
137
+ `bdd2pw scaffold ... --llm openai` now works. The `--llm-model`
138
+ help text updated to reflect both providers' defaults.
139
+
140
+ ### `optionalDependencies`
141
+
142
+ `openai ^4.77.0` added alongside `@anthropic-ai/sdk`. Like the
143
+ Anthropic SDK, it's loaded defensively via `require()` so users who
144
+ only want Anthropic don't need to install the OpenAI SDK and vice
145
+ versa. Missing-package error message points to `npm install openai`.
146
+
147
+ ### Cache compat
148
+
149
+ Cache keys include the model name (since v2.0), so a scaffold
150
+ cached under `claude-sonnet-4-6` will NOT hit the cache when run
151
+ under `gpt-4o-mini` — you get a fresh provider call. Within the
152
+ same model, cache hits work identically regardless of how many
153
+ times you switch providers across scaffold runs.
154
+
155
+ ### Tests
156
+
157
+ `tests/unit/v3110OpenAI.test.ts`:
158
+ - Default model + DEFAULT_PRICING lookup.
159
+ - generateBinding succeeds with a well-formed JSON response.
160
+ - generateBatchBindings produces N bindings from ONE provider
161
+ call (cache misses → single batched prompt → JSON array → N
162
+ bindings).
163
+ - Budget exhaustion returns an error without making a provider call.
164
+ - Missing API key short-circuits before the SDK loads.
165
+ - Malformed JSON response surfaces a parse error.
166
+
167
+ ## [3.10.0] — 2026-06-06
168
+
169
+ ### Added — self-healing stats sidecar + `bdd2pw heal-stats` CLI
170
+
171
+ v1.1+ has shipped a runtime `healOrThrow` helper that emits
172
+ `register` / `heal_attempt` / `healed` / `heal_unavailable` events
173
+ to `<repo>/artefacts/heal-events.jsonl`. Until now those events
174
+ sat in a JSONL file with no offline analyzer — operators had to
175
+ grep the file themselves to see if healing was working.
176
+
177
+ v3.10.0 adds:
178
+
179
+ **1. `bdd2pw heal-stats <repo>` CLI** — reads
180
+ `<repo>/artefacts/heal-events.jsonl` and writes
181
+ `<repo>/artefacts/heal-stats.json` with:
182
+
183
+ {
184
+ "version": "3.10.0",
185
+ "generatedAt": "2026-06-06T...",
186
+ "source": "<events file>",
187
+ "totals": {
188
+ "registrations": 47,
189
+ "healAttempts": 6,
190
+ "healed": 4,
191
+ "healUnavailable": 2,
192
+ "healRate": 0.6667,
193
+ "uniqueFields": 23,
194
+ "uniquePages": 3
195
+ },
196
+ "topFailingFields": [
197
+ { "page": "LoginPage", "name": "submitButton",
198
+ "attempts": 3, "healed": 2 },
199
+ ...
200
+ ],
201
+ "topErrors": [
202
+ { "error": "timeout <n>ms exceeded", "count": 4 },
203
+ ...
204
+ ],
205
+ "topCandidates": [
206
+ { "selector": "[data-testid='submit']", "promotions": 2,
207
+ "averageConfidence": 0.87 },
208
+ ...
209
+ ],
210
+ "retryLatencyMs": { "p50": 1240, "p95": 3010,
211
+ "min": 880, "max": 3010 },
212
+ "perScenario": [
213
+ { "scenario": "User can log in", "attempts": 1, "healed": 1 },
214
+ ...
215
+ ]
216
+ }
217
+
218
+ Where v3.9.0's `llm-stats.json` measures the LLM batching ROI per
219
+ scaffold, v3.10.0's `heal-stats.json` measures the self-healing
220
+ ROI per TEST RUN.
221
+
222
+ **2. New module `src/reports/healStats.ts`** — pure
223
+ `aggregate(events, source, topN)` function plus the wrapper
224
+ `analyseHealStats(opts)` that resolves the input path
225
+ (file / repo-dir / artefacts-subdir) and writes the sidecar.
226
+
227
+ **3. Error normalisation.** The aggregator collapses error messages
228
+ into stable buckets (lowercase, strip "Error:"/"TimeoutError:"
229
+ prefixes, replace runs of 3+ digits with `<n>`) so transient
230
+ timestamps / IDs don't fragment the histogram.
231
+
232
+ **4. Retry latency derivation.** Pairs each `heal_attempt` with its
233
+ matching `healed` (by `page+name+method`) and reports the timestamp
234
+ delta as the retry latency. Computes p50 / p95 / min / max across
235
+ the run.
236
+
237
+ **5. Graceful empty-input behaviour.** Pointing the CLI at a repo
238
+ with no heal-events.jsonl writes a zero-event summary instead of
239
+ failing — `bdd2pw heal-stats` is now safe to run unconditionally
240
+ in CI after `npx playwright test`.
241
+
242
+ ### Tests
243
+
244
+ `tests/unit/v3100HealStats.test.ts`:
245
+ - Empty input → all-zero summary.
246
+ - Mixed register / heal_attempt / healed / heal_unavailable sequence
247
+ aggregates correctly (counts, healRate, topFailingFields,
248
+ topErrors, topCandidates, p50/p95 latency, per-scenario rollup).
249
+ - `topN` honored — top-3 returns 3 entries from 5 distinct fields.
250
+ - End-to-end: write JSONL → `analyseHealStats(file)` → read JSON
251
+ back and verify shape + version stamp.
252
+ - Missing-file safety: pointing at a directory with no
253
+ heal-events.jsonl returns total=0 and writes an empty summary.
254
+ - Repo-path resolution: passing a directory finds
255
+ `artefacts/heal-events.jsonl` automatically.
256
+
12
257
  ## [3.9.0] — 2026-06-05
13
258
 
14
259
  ### Added — opt-in LLM telemetry sidecar
package/README.md CHANGED
@@ -42,9 +42,12 @@ Point it at a `.feature` file and a URL. It parses the Gherkin, scans the live p
42
42
 
43
43
  > **The pitch.** Run `bdd2pw scaffold` and you get a Playwright TS repo where `npx playwright test` runs against the real site. For specific fixtures, all green. For vague ones, the 60-90% you'd otherwise hand-write is done; you finish the rest — or you let the governed LLM finish them.
44
44
 
45
- ## What's new in v3.9.0
45
+ ## What's new in v3.12.0
46
46
 
47
- - **NEW** `llmStats: true` writes `<repo>/artefacts/llm-stats.json` with per-call latency, token counts, cache hit rate, and an estimated cost in USD. Finally makes the v3.5 batching ROI measurable per run.
47
+ - **NEW** Gemini provider — three-provider parity is now complete. `--llm gemini` or `LLMClientOptions.provider: "gemini"` defaults to `gemini-2.5-flash` ($0.10/M input — the cheapest model across all three providers). Same cache, governance, batching, and telemetry pipeline as Anthropic and OpenAI. Install only when needed via `npm install @google/generative-ai`.
48
+ - OpenAI provider with full parity (cache, governance, batching, telemetry). `--llm openai` defaults to `gpt-4o-mini` (v3.11.0).
49
+ - `bdd2pw heal-stats <repo>` CLI reads `<repo>/artefacts/heal-events.jsonl` and writes a heal-stats.json sidecar with heal rate, top failing fields, retry latency, candidate-selector promotions (v3.10.0).
50
+ - `llmStats: true` writes `<repo>/artefacts/llm-stats.json` with per-call latency, token counts, cache hit rate, and an estimated cost in USD (v3.9.0).
48
51
  - Seven domain rule packs (banking, healthcare, insurance, retail, gov, education, telecom) — ~140 industry-specific patterns total.
49
52
  - Per-scenario LLM batching cuts Anthropic spend by ~75% on unmatched-heavy scaffolds.
50
53
  - `bdd2pw propose-rules` CLI clusters past LLM bindings into draft regex proposals — turning the offline-review pipeline into one command.
@@ -348,23 +351,23 @@ output/
348
351
  | v3.6 | Diagnostics + auto-rules | Rule-trace block in `BDD_REVIEW.md`; new `bdd2pw propose-rules` CLI clustering candidate-rules.jsonl into draft regex |
349
352
  | v3.7.1 | Regression fixes | PascalCase className shadow fix; `test.step` wrapping regression-asserted |
350
353
  | v3.8.1 | More domain packs | Retail / gov / education / telecom packs added — seven total (~140 industry-specific rules) |
351
- | **v3.9.0 (current)** | Telemetry | `artefacts/llm-stats.json` sidecar — per-call latency + tokens + cache hit rate + estimated cost. Makes v3.5 batching ROI measurable per scaffold. |
354
+ | v3.9.0 | Telemetry | `artefacts/llm-stats.json` sidecar — per-call latency + tokens + cache hit rate + estimated cost. Makes v3.5 batching ROI measurable per scaffold. |
355
+ | v3.10.0 | Heal stats | `bdd2pw heal-stats <repo>` CLI consumes `artefacts/heal-events.jsonl` and writes `heal-stats.json` with heal rate, top failing fields, top error patterns, retry latency, candidate-selector promotions. Self-healing ROI per test run. |
356
+ | v3.11.0 | OpenAI provider | `LLMClientOptions.provider: "openai"` lands with cache + governance + batching + telemetry parity. Default model `gpt-4o-mini` (~17x cheaper than `gpt-4o` for structured-JSON tasks). |
357
+ | **v3.12.0 (current)** | Gemini provider | `LLMClientOptions.provider: "gemini"` lands with full parity. Default model `gemini-2.5-flash` ($0.10/M input — cheapest across all three providers). Three-provider parity complete. |
352
358
 
353
359
  ### Next 6 months (Jun 2026 → Nov 2026, ~2 releases/month)
354
360
 
355
361
  | Target | Version | Theme | Headline |
356
362
  |---|---|---|---|
357
- | Jun 2026 | **v3.10.0** | OpenAI provider | `LLMClientOptions.provider: "openai"` lands; multi-provider client factory; same governance + cache pipeline. |
358
- | Jul 2026 | **v3.11.0** | Gemini provider | `LLMClientOptions.provider: "gemini"` lands; full three-provider parity (Anthropic / OpenAI / Gemini). |
359
- | Jul 2026 | **v3.12.0** | Auto-rules | `bdd2pw apply-proposals --interactive` — walks the human through each v3.6 proposal, validates the regex compiles + matches the sample texts, optionally appends to `stepMatcher.ts`. Closes the propose-rules loop. |
363
+ | Aug 2026 | **v3.13.0** | Auto-rules | `bdd2pw apply-proposals --interactive` — walks the human through each v3.6 proposal, validates the regex compiles + matches the sample texts, optionally appends to `stepMatcher.ts`. Closes the propose-rules loop. |
360
364
  | Aug 2026 | **v4.0.0** | Modern defaults | Semver-major reset: bump Anthropic default model, retire v2.x deprecated APIs, switch test-signature defaults to current best practice. Migration guide ships alongside. |
361
- | Aug 2026 | **v4.1.0** | sel2pw merge | sel2pw migrated onto `@vijaypjavvadi/pw-emit` — three packages share one emitter. All future v3.x emitter improvements automatically flow to Selenium users. |
365
+ | Sep 2026 | **v4.1.0** | sel2pw merge | sel2pw migrated onto `@vijaypjavvadi/pw-emit` — three packages share one emitter. All future v3.x emitter improvements automatically flow to Selenium users. |
362
366
  | Sep 2026 | **v4.2.0** | Domain packs | Three more opt-in packs: **fintech** (KYC, AML, trading desks), **real-estate** (MLS, listings, escrow), **hospitality** (PMS, reservations, OTA). ~60 more rules. |
363
- | Sep 2026 | **v4.3.0** | API v2 | WebSocket assertion rules, multipart file-upload patterns, GraphQL query / mutation / subscription rules. Extends v3.0's API testing surface. |
367
+ | Oct 2026 | **v4.3.0** | API v2 | WebSocket assertion rules, multipart file-upload patterns, GraphQL query / mutation / subscription rules. Extends v3.0's API testing surface. |
364
368
  | Oct 2026 | **v4.4.0** | Coverage analyzer | `bdd2pw coverage` CLI: which deterministic rules fired on which features across a fleet, per-pack hit rate, dead-rule report, suggestion to retire unused rules. |
365
- | Oct 2026 | **v4.5.0** | CI/CD templates | Optional scaffolder output: GitHub Actions / GitLab CI / Azure Pipelines / CircleCI starter workflows wired to run the generated specs. Opt-in via `--ci <provider>`. |
369
+ | Nov 2026 | **v4.5.0** | CI/CD templates | Optional scaffolder output: GitHub Actions / GitLab CI / Azure Pipelines / CircleCI starter workflows wired to run the generated specs. Opt-in via `--ci <provider>`. |
366
370
  | Nov 2026 | **v4.6.0** | Mobile dialect | Touch / swipe / scroll-into-view rules + responsive viewport assertions. Reuses the same emitter pipeline; opt-in via `domains: ["mobile"]`. |
367
- | Nov 2026 | **v4.7.0** | i18n Gherkin | Accept Cucumber-compatible non-English keywords (Spanish, German, French, Portuguese, Japanese, …). Lets bdd2pw scaffold from `.feature` files written in any of the ~70 languages Cucumber supports. |
368
371
 
369
372
  Each release is shaped to be self-contained, ship in ~2 weeks, and keep `domains: []` byte-stable for existing users so the upgrade path stays painless.
370
373
 
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
@@ -60,9 +61,9 @@ program
60
61
  .option("--headed", "Show browser during MCP scan", false)
61
62
  .option("--snapshot-file <path>", "Read elements from a JSON file instead of launching a browser")
62
63
  .option("--no-discovery", "Skip page discovery entirely (rule-only probing). Field-referencing rules will fall to TODO.")
63
- .option("--llm <provider>", "Enable LLM fallback for unmatched steps. v2.0: only 'anthropic' wired; openai/gemini land in v2.1.")
64
+ .option("--llm <provider>", "Enable LLM fallback for unmatched steps. v3.12.0: 'anthropic', 'openai', or 'gemini'.")
64
65
  .option("--governance-url <url>", "ai-governance sidecar URL — every prompt is sanitised here before leaving the perimeter (fail-closed).", "http://localhost:4900")
65
- .option("--llm-model <model>", "Override the LLM model (default: claude-sonnet-4-6 for anthropic).")
66
+ .option("--llm-model <model>", "Override the LLM model. Defaults: anthropic→claude-sonnet-4-6, openai→gpt-4o-mini, gemini→gemini-2.5-flash.")
66
67
  .option("--llm-max-calls <n>", "Max LLM provider calls per scaffold. Default 50. Cache hits don't count.", "50")
67
68
  .option("--llm-cache <path>", "SQLite cache path. Default <repo>/.bdd2pw/llm-cache.sqlite. Use ':memory:' for one-shot.")
68
69
  .option("--llm-skip-governance", "DO NOT USE in production — bypass the sidecar sanitisation step. Test-only escape hatch.", false)
@@ -75,14 +76,18 @@ 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
81
83
  // top-level `llm` field stays for backwards compat; `llmConfig` is the
82
- // real one used by scaffold().
83
- const llmConfig = opts.llm === "anthropic"
84
- ? {
85
- provider: "anthropic",
84
+ // real one used by scaffold(). v3.11.0 — accept openai too.
85
+ const llmProvider = opts.llm === "anthropic" || opts.llm === "openai" || opts.llm === "gemini"
86
+ ? opts.llm
87
+ : null;
88
+ const llmConfig = llmProvider
89
+ ? ({
90
+ provider: llmProvider,
86
91
  model: opts.llmModel,
87
92
  governanceUrl: opts.governanceUrl,
88
93
  maxCalls: opts.llmMaxCalls
@@ -100,7 +105,7 @@ program
100
105
  governanceTimeoutMs: opts.llmGovernanceTimeoutMs
101
106
  ? Number(opts.llmGovernanceTimeoutMs)
102
107
  : undefined,
103
- }
108
+ })
104
109
  : undefined;
105
110
  const result = await (0, index_1.scaffold)({
106
111
  feature: path.resolve(feature),
@@ -122,6 +127,8 @@ program
122
127
  // Commander negates --no-discovery into opts.discovery=false
123
128
  noDiscovery: opts.discovery === false,
124
129
  selfHealing: opts.selfHealing,
130
+ // v3.9.0 — telemetry sidecar
131
+ llmStats: opts.llmStats === true,
125
132
  });
126
133
  logger_1.logger.info({ result }, "scaffold complete");
127
134
  }
@@ -235,6 +242,32 @@ program
235
242
  process.stdout.write(`\n${result.proposalsWritten} proposal(s) written to ${result.outputPath} ` +
236
243
  `(from ${result.totalCandidates} candidate entries).\n`);
237
244
  });
245
+ /**
246
+ * v3.10.0 — heal-stats subcommand. Reads `<repo>/artefacts/heal-events.jsonl`
247
+ * (produced by the runtime `healOrThrow` helper) and writes
248
+ * `<repo>/artefacts/heal-stats.json` summarising heal attempts,
249
+ * success rate, top failing fields, top error patterns, retry latency,
250
+ * and the candidate selectors that got promoted. Run after
251
+ * `npx playwright test` in CI to track self-healing ROI per test run.
252
+ */
253
+ program
254
+ .command("heal-stats")
255
+ .description("Aggregate <repo>/artefacts/heal-events.jsonl into a heal-stats.json sidecar.")
256
+ .argument("<input>", "Path to heal-events.jsonl OR the test repo containing artefacts/heal-events.jsonl")
257
+ .option("--out <path>", "Where to write heal-stats.json. Defaults to next to the events file.")
258
+ .option("--top <n>", "How many entries to keep in each ranked list (failing fields, errors, candidates, scenarios). Default 10.", "10")
259
+ .action(async (input, raw) => {
260
+ const result = await (0, healStats_1.analyseHealStats)({
261
+ inputPath: input,
262
+ outputPath: raw.out,
263
+ topN: raw.top ? Number(raw.top) : undefined,
264
+ });
265
+ logger_1.logger.info({
266
+ outputPath: result.outputPath,
267
+ totalEvents: result.totalEvents,
268
+ }, "heal-stats: complete");
269
+ process.stdout.write(`\nheal-stats: wrote ${result.outputPath} (parsed ${result.totalEvents} event(s)).\n`);
270
+ });
238
271
  program.parseAsync(process.argv).catch((err) => {
239
272
  logger_1.logger.error({ err }, "fatal");
240
273
  process.exit(1);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;AACA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,yCAAoC;AACpC,2CAA6B;AAC7B,mCAAuD;AACvD,+BAAqC;AACrC,2CAAwC;AAExC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CACV,4EAA4E,CAC7E;KACA,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC;AAE/C,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CACV,iFAAiF,CAClF;KACA,QAAQ,CAAC,WAAW,EAAE,iCAAiC,CAAC;KACxD,cAAc,CAAC,aAAa,EAAE,4BAA4B,CAAC;KAC3D,cAAc,CAAC,eAAe,EAAE,qCAAqC,CAAC;KACtE,cAAc,CAAC,cAAc,EAAE,gDAAgD,CAAC;KAChF,MAAM,CAAC,gBAAgB,EAAE,sDAAsD,CAAC;KAChF,MAAM,CAAC,wBAAwB,EAAE,sCAAsC,CAAC;KACxE,MAAM,CAAC,UAAU,EAAE,8BAA8B,EAAE,KAAK,CAAC;KACzD,MAAM,CAAC,wBAAwB,EAAE,+DAA+D,CAAC;KACjG,MAAM,CACL,gBAAgB,EAChB,8FAA8F,CAC/F;KACA,MAAM,CAAC,kBAAkB,EAAE,oGAAoG,CAAC;KAChI,MAAM,CACL,wBAAwB,EACxB,wGAAwG,EACxG,uBAAuB,CACxB;KACA,MAAM,CAAC,qBAAqB,EAAE,oEAAoE,CAAC;KACnG,MAAM,CAAC,qBAAqB,EAAE,0EAA0E,EAAE,IAAI,CAAC;KAC/G,MAAM,CAAC,oBAAoB,EAAE,0FAA0F,CAAC;KACxH,MAAM,CAAC,uBAAuB,EAAE,0FAA0F,EAAE,KAAK,CAAC;KAClI,MAAM,CAAC,2BAA2B,EAAE,6GAA6G,EAAE,OAAO,CAAC;KAC3J,MAAM,CAAC,+BAA+B,EAAE,8DAA8D,EAAE,OAAO,CAAC;KAChH,MAAM,CAAC,iCAAiC,EAAE,4DAA4D,EAAE,OAAO,CAAC;KAChH,MAAM,CAAC,mBAAmB,EAAE,6CAA6C,CAAC;KAC1E,MAAM,CAAC,WAAW,EAAE,2BAA2B,EAAE,KAAK,CAAC;KACvD,MAAM,CAAC,eAAe,EAAE,wBAAwB,CAAC;KACjD,MAAM,CAAC,aAAa,EAAE,uCAAuC,EAAE,KAAK,CAAC;KACrE,MAAM,CAAC,SAAS,EAAE,+BAA+B,EAAE,KAAK,CAAC;KACzD,MAAM,CACL,gBAAgB,EAChB,kNAAkN,EAClN,KAAK,CACN;KACA,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;IACtC,IAAI,CAAC;QACH,qEAAqE;QACrE,uEAAuE;QACvE,+BAA+B;QAC/B,MAAM,SAAS,GACb,IAAI,CAAC,GAAG,KAAK,WAAW;YACtB,CAAC,CAAC;gBACE,QAAQ,EAAE,WAAoB;gBAC9B,KAAK,EAAE,IAAI,CAAC,QAAQ;gBACpB,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,QAAQ,EAAE,IAAI,CAAC,WAAW;oBACxB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;oBAC1B,CAAC,CAAC,SAAS;gBACb,SAAS,EAAE,IAAI,CAAC,QAAQ;gBACxB,cAAc,EAAE,IAAI,CAAC,iBAAiB;gBACtC,mBAAmB;gBACnB,aAAa,EAAE,IAAI,CAAC,gBAAgB;oBAClC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;oBAC/B,CAAC,CAAC,SAAS;gBACb,iBAAiB,EAAE,IAAI,CAAC,oBAAoB;oBAC1C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC;oBACnC,CAAC,CAAC,SAAS;gBACb,mBAAmB,EAAE,IAAI,CAAC,sBAAsB;oBAC9C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC;oBACrC,CAAC,CAAC,SAAS;aACd;YACH,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,MAAM,GAAG,MAAM,IAAA,gBAAQ,EAAC;YAC5B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAC9B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7B,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1D,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,SAAS;YACT,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,KAAK;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,6DAA6D;YAC7D,WAAW,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK;YACrC,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;QACH,eAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,qEAAqE,CAAC;KAClF,QAAQ,CAAC,WAAW,EAAE,iCAAiC,CAAC;KACxD,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC;KAC5C,MAAM,CAAC,wBAAwB,EAAE,sCAAsC,CAAC;KACxE,MAAM,CAAC,UAAU,EAAE,8BAA8B,EAAE,KAAK,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,eAAO,EAAC;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAC9B,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,oEAAoE,CAAC;KACjF,cAAc,CAAC,eAAe,EAAE,wBAAwB,CAAC;KACzD,cAAc,CAAC,aAAa,EAAE,gBAAgB,CAAC;KAC/C,cAAc,CAAC,cAAc,EAAE,6BAA6B,CAAC;KAC7D,MAAM,CAAC,wBAAwB,EAAE,sCAAsC,CAAC;KACxE,MAAM,CAAC,UAAU,EAAE,8BAA8B,EAAE,KAAK,CAAC;KACzD,MAAM,CAAC,mBAAmB,EAAE,6CAA6C,CAAC;KAC1E,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,iBAAS,EAAC;YAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,eAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,eAAe,EAAE,mBAAmB,EAAE,MAAM,CAAC;KACpD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,EAAE,WAAW,EAAE,GAAG,wDAAa,UAAU,GAAC,CAAC;IACjD,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEL;;GAEG;AACH,SAAS,WAAW,CAAC,GAAY;IAC/B,MAAM,IAAI,GAAI,GAAyB,EAAE,IAAI,IAAI,EAAE,CAAC;IACpD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,mBAAmB;YACtB,OAAO,CAAC,CAAC;QACX,KAAK,iBAAiB;YACpB,OAAO,CAAC,CAAC;QACX,KAAK,UAAU,CAAC;QAChB,KAAK,iBAAiB;YACpB,OAAO,CAAC,CAAC;QACX,KAAK,yBAAyB;YAC5B,OAAO,CAAC,CAAC;QACX;YACE,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CACV,yGAAyG,CAC1G;KACA,QAAQ,CACP,SAAS,EACT,kEAAkE,CACnE;KACA,MAAM,CACL,cAAc,EACd,iEAAiE,CAClE;KACA,MAAM,CACL,wBAAwB,EACxB,qDAAqD,EACrD,GAAG,CACJ;KACA,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,GAA8C,EAAE,EAAE;IAC9E,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAY,EAAC;QAChC,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,GAAG,CAAC,GAAG;QACnB,cAAc,EAAE,GAAG,CAAC,cAAc;YAChC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;YAC5B,CAAC,CAAC,SAAS;KACd,CAAC,CAAC;IACH,eAAM,CAAC,IAAI,CACT;QACE,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,eAAe,EAAE,MAAM,CAAC,eAAe;KACxC,EACD,yBAAyB,CAC1B,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,MAAM,CAAC,gBAAgB,2BAA2B,MAAM,CAAC,UAAU,GAAG;QACzE,SAAS,MAAM,CAAC,eAAe,wBAAwB,CAC1D,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Gemini LLM client — v3.12.0.
3
+ *
4
+ * Implements the same `LLMClient` interface as `AnthropicLLMClient` and
5
+ * `OpenAILLMClient`: single-step `generateBinding`, batched
6
+ * `generateBatchBindings`, cache hit accounting, budget tracking,
7
+ * governance sanitisation, step deadlines, provider timeouts.
8
+ *
9
+ * SDK-shape differences from Anthropic / OpenAI:
10
+ *
11
+ * Anthropic OpenAI Gemini
12
+ * -------------------------------- ------------------------------ ------------------------------------
13
+ * anthropic.messages.create({ openai.chat.completions.create({ model.generateContent({
14
+ * system: SYSTEM_PROMPT, messages: [ systemInstruction: SYSTEM_PROMPT,
15
+ * messages: [ { role: 'system', ... }, contents: [
16
+ * { role: 'user', content } { role: 'user', ... } { role: 'user',
17
+ * ] ] parts: [{ text: prompt }] }
18
+ * }) }) ]
19
+ * })
20
+ *
21
+ * resp.content[0].text resp.choices[0].message.content resp.response.text()
22
+ * resp.usage.input_tokens resp.usage.prompt_tokens resp.response.usageMetadata.promptTokenCount
23
+ * resp.usage.output_tokens resp.usage.completion_tokens resp.response.usageMetadata.candidatesTokenCount
24
+ *
25
+ * The prompt machinery (`SYSTEM_PROMPT`, `buildUserPrompt`,
26
+ * `buildBatchUserPrompt`, `cacheKey`), the parser (`parseBindingJson`),
27
+ * the cache (`openSqliteCache`), and the governance client are shared
28
+ * with the other two providers. Cache keys include the model name —
29
+ * cross-provider hits only fire when the model strings match.
30
+ *
31
+ * Default model: `gemini-2.5-flash`. Reasoning: bdd2pw's task is
32
+ * structured JSON output over regex-shaped deterministic patterns.
33
+ * Flash handles it reliably and runs even cheaper than gpt-4o-mini.
34
+ * Override via `LLMClientOptions.model`.
35
+ *
36
+ * Note on JSON output: Gemini's structured-output mode would let us
37
+ * request a JSON schema directly. We deliberately don't — the prompt
38
+ * already constrains the response shape, and going through the same
39
+ * text-then-parse pipeline as the other providers keeps the
40
+ * parseBindingJson behavior provider-agnostic.
41
+ */
42
+ import type { BindingCache } from "./cache";
43
+ import type { GenerateBindingInput, GenerateBindingResult, LLMClient, LLMClientOptions } from "./types";
44
+ export declare class GeminiLLMClient implements LLMClient {
45
+ private model;
46
+ private apiKey;
47
+ private maxCalls;
48
+ private skipGovernance;
49
+ private log;
50
+ private governance;
51
+ private cache;
52
+ private cachePath;
53
+ private callsCounter;
54
+ private attemptsCounter;
55
+ private genai;
56
+ private modelHandle;
57
+ private cachePersistent;
58
+ private cacheFallbackReason;
59
+ private providerTimeoutMs;
60
+ constructor(opts: LLMClientOptions, cachePathDefault: string);
61
+ ensureCache(): Promise<BindingCache>;
62
+ budgetExhausted(): boolean;
63
+ callsMade(): number;
64
+ callsAttempted(): number;
65
+ cacheBackendPersistent(): boolean | null;
66
+ cacheBackendFallbackReason(): string | undefined;
67
+ /**
68
+ * Single-step generation. Cache → governance → Gemini → parse.
69
+ * Mirrors `AnthropicLLMClient.generateBinding` and `OpenAILLMClient.generateBinding`.
70
+ */
71
+ generateBinding(input: GenerateBindingInput): Promise<GenerateBindingResult>;
72
+ /**
73
+ * Batched generation — same per-step cache lookup + single batched
74
+ * prompt as the Anthropic / OpenAI clients. JSON array response
75
+ * parsed slot by slot through `parseBindingJson`.
76
+ */
77
+ generateBatchBindings(inputs: GenerateBindingInput[]): Promise<GenerateBindingResult[]>;
78
+ /**
79
+ * Wraps a promise with a deadline. Gemini's generateContent has no
80
+ * native timeout option (unlike Anthropic/OpenAI SDKs), so we race
81
+ * the SDK call against a setTimeout.
82
+ */
83
+ private withTimeout;
84
+ private lazyModel;
85
+ close(): Promise<void>;
86
+ }