sela-core 0.1.0-alpha.2 → 0.1.0-alpha.31

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 CHANGED
@@ -1,103 +1,856 @@
1
- # Sela
1
+ # Sela Documentation
2
2
 
3
- ## Getting started
3
+ > **Self-Healing Reliability Engine for Playwright**
4
+ > _Version 1.0.8_
4
5
 
5
- To make it easy for you to get started with GitLab, here's a list of recommended next steps.
6
+ ---
7
+
8
+ ## Table of Contents
9
+
10
+ 1. [Introduction - The Problem & The Solution](#1-introduction)
11
+ 2. [The Safety-First Philosophy](#2-the-safety-first-philosophy)
12
+ 3. [Core Concepts](#3-core-concepts)
13
+ 4. [Quick Start](#4-quick-start)
14
+ 5. [CLI Reference](#5-cli-reference)
15
+ 6. [CI/CD Integration & Sharding](#6-cicd-integration--sharding)
16
+ 7. [Reporting & Insights](#7-reporting--insights)
17
+ 8. [Advanced Configuration](#8-advanced-configuration)
18
+ 9. [Error Reference](#9-error-reference)
19
+
20
+ ---
21
+
22
+ ## 1. Introduction
23
+
24
+ ### The Problem: Tests That Break Without Warning
25
+
26
+ Selector fragility is the silent killer of test suite ROI. A frontend refactor ships on Friday, and by Monday your CI pipeline is red - not because the application broke, but because a `div` got an `id` rename, a class was reorganised, or a component hierarchy shifted by one level. Your engineers spend the morning triaging failures that have nothing to do with bugs.
27
+
28
+ At scale, this compounds fast. A team with 2,000 end-to-end tests might absorb dozens of locator-maintenance hours per sprint - engineers doing rote, zero-insight work instead of shipping features.
29
+
30
+ ### What is Sela?
31
+
32
+ Sela is a **Self-Healing Reliability Engine** for Playwright. It intercepts locator failures at runtime, uses a multi-stage AI pipeline to recover the correct selector, and - after passing a rigorous multi-gate safety review - surgically patches your source code. The broken test passes. Your spec file is updated. No human intervention required.
33
+
34
+ Sela is **not** a test generator or a code scaffolding tool. It is a reliability layer that runs inside your existing Playwright setup, invisible during green runs, and active only when something breaks. Think of it as an immune system for your test suite.
35
+
36
+ ### Why Sela?
37
+
38
+ Most "AI testing" tools either generate new tests from scratch or produce brittle selector suggestions you have to manually review. Sela is different in three fundamental ways:
39
+
40
+ | Dimension | Typical AI Tools | Sela |
41
+ | ------------------- | -------------------------- | ------------------------------------- |
42
+ | **When it acts** | Test generation (pre-run) | Failure recovery (runtime) |
43
+ | **What it changes** | Generates new files | Surgically patches existing source |
44
+ | **Safety model** | None / "review everything" | 8-gate automated safety pipeline |
45
+ | **CI integration** | Standalone | Native Playwright Reporter & sharding |
46
+ | **Source of truth** | The AI | Your codebase + DNA fingerprints |
47
+
48
+ The key differentiator is **safety with autonomy**. Sela is designed to touch your source code unattended in CI - which means its safety guarantees have to be enterprise-grade. Every heal goes through a multi-gate verification pipeline before a single byte is written to disk.
49
+
50
+ ---
51
+
52
+ ## 2. The Safety-First Philosophy
53
+
54
+ > _Sela will never make your test suite less trustworthy in order to make it green._
55
+
56
+ This is the core design constraint. A self-healing engine that silently swaps a **Login** button for a **Logout** button would be worse than no healing at all. Sela's entire architecture is built around preventing exactly this class of failure.
57
+
58
+ ### How Sela Verifies Every Fix Before Touching Your Codebase
59
+
60
+ When a locator fails, Sela goes through the following sequence. Each stage is a gate - a failure at any gate stops the process and records the event for your review.
61
+
62
+ ```
63
+ Locator Failure Detected
64
+
65
+
66
+ ┌───────────────────────┐
67
+ │ 1. AI Selector Fix │ LLM proposes a candidate selector + confidence score
68
+ └───────────┬───────────┘
69
+
70
+
71
+ ┌───────────────────────┐
72
+ │ 2. Live DOM Probe │ Sela finds the element live on the page (1.5s timeout)
73
+ └───────────┬───────────┘
74
+
75
+
76
+ ┌───────────────────────┐
77
+ │ 3. DNA Capture │ Atomic snapshot of the candidate element's full identity
78
+ └───────────┬───────────┘
79
+
80
+
81
+ ┌───────────────────────────────────────────────────────────────┐
82
+ │ SafetyGuard Pipeline │
83
+ │ Gate 1: Visibility Check (ghost / occluded element?) │
84
+ │ Gate 2: Hard Confidence Stop (AI confidence < threshold?) │
85
+ │ Gate 3: Zero-Trust Content Verification │
86
+ │ Gate 4: Structural-Only Change Check │
87
+ │ Gate 5: Binary Semantic-Opposite Guard │
88
+ │ Gate 6: Functional Role Classification │
89
+ │ Gate 6.5: Dangerous-Sink Transition Rule │
90
+ │ Gate 7: Intent Auditor (second AI model - haiku) │
91
+ │ Gate 8: Confidence Tier Decision │
92
+ └───────────────────────────────────────────────────────────────┘
93
+
94
+
95
+ APPLY / HOLD / REJECT
96
+
97
+ ▼ (APPLY only)
98
+ ┌───────────────────────┐
99
+ │ AST Source Mutation │ Surgical, comment-preserving, type-checked write
100
+ └───────────────────────┘
101
+ ```
102
+
103
+ > 💡 **Suggested diagram:** Replace the ASCII art above with an interactive vertical flow diagram showing each gate as a coloured node (green = pass, red = reject, amber = hold).
104
+
105
+ ### The 8-Gate SafetyGuard Pipeline - In Detail
106
+
107
+ #### Gate 1: Visibility Check
108
+
109
+ Before anything else, Sela checks whether the candidate element is actually visible and interactive. Six "ghost conditions" are evaluated:
110
+
111
+ - `G1` - `display: none`
112
+ - `G2` - `visibility: hidden`
113
+ - `G3` - `opacity < 0.05`
114
+ - `G4` - `pointer-events: none` with no interactable child
115
+ - `G5` - zero width and height
116
+ - `G6` - `content-visibility: hidden`
117
+
118
+ A ghost element results in an immediate `FAIL_HARD` - there is no scenario where healing to an invisible element is correct. Occlusion (another element covering the candidate at its centre point) is also checked: on `main`/`master` branches it is `FAIL_HARD`; on feature branches it is `REQUIRES_REVIEW`.
119
+
120
+ #### Gate 2: Hard Confidence Stop
121
+
122
+ The AI healing model returns a numeric confidence score (0–100). If this score falls below `confidenceHardStop` (default: **85**), the heal is blocked unconditionally. This gate is intentionally aggressive - a low-confidence suggestion should never reach your source.
123
+
124
+ #### Gate 3: Zero-Trust Content Verification
125
+
126
+ Sela compares the live `innerText` of the candidate element against the DNA baseline text captured during the original test run. If the AI omitted a `contentChange` assessment but the text has changed, Sela synthesises one and forces a full inversion check. Nothing is assumed correct.
127
+
128
+ #### Gate 4: Structural-Only Change Check
129
+
130
+ If the selector changed but no text content changed, the risk profile drops significantly. A purely structural heal (e.g., an `id` rename with identical label text) is fast-tracked to `SAFE` if confidence is high enough, or `REQUIRES_REVIEW` if it falls below `confidenceReviewThreshold`.
131
+
132
+ #### Gate 5: Binary Semantic-Opposite Guard
133
+
134
+ A hardcoded vocabulary of semantic antonym pairs - `welcome`/`denied`, `login`/`logout`, `enable`/`disable`, and others - is checked against the old and new element text. A match means the element's meaning has inverted. This results in `FAIL_HARD`, regardless of AI confidence.
135
+
136
+ #### Gate 6: Functional Role Classification
137
+
138
+ Sela classifies elements into functional roles using word-boundary regex matching:
139
+
140
+ | Role | Examples |
141
+ | ----------------- | ------------------------------ |
142
+ | `SUBMIT` | Submit, Confirm, Save, Apply |
143
+ | `CANCEL` | Cancel, Discard, Abort |
144
+ | `DELETE` | Delete, Remove, Destroy |
145
+ | `NAVIGATE` | Back, Next, Go to |
146
+ | `AUTH` | Sign in, Log out, Authenticate |
147
+ | `STATUS_POSITIVE` | Success, Approved, Active |
148
+ | `STATUS_NEGATIVE` | Error, Rejected, Inactive |
149
+
150
+ Cross-role swaps (e.g., healing from a `SUBMIT` button to a `CANCEL` button) trigger escalated responses:
151
+
152
+ - In **assertion mode**: `BLOCKED`
153
+ - In **action mode**: `REQUIRES_REVIEW`
154
+ - `STATUS_POSITIVE` ↔ `STATUS_NEGATIVE`: always `FAIL_HARD`
155
+
156
+ #### Gate 6.5: Dangerous-Sink Transition Rule
157
+
158
+ A specialised rule that watches for dynamic role mutations. If the new element falls into the `DELETE` or `AUTH` role and the old element did not, the pipeline sets a `forceAudit` flag - bypassing all confidence-based shortcuts and forcing the Intent Auditor (Gate 7) to evaluate the change regardless of score.
159
+
160
+ #### Gate 7: The Intent Auditor
161
+
162
+ When a heal is flagged for deeper review, a second AI model (Claude Haiku) acts as an independent auditor. It receives the DNA before and after snapshots and evaluates whether the semantic intent of the locator is preserved. It returns one of three verdicts:
163
+
164
+ - **`CONSISTENT`** - The element serves the same purpose. Proceed.
165
+ - **`SUSPICIOUS`** - Intent is uncertain. Blocked in assertion mode; held for review in action mode.
166
+ - **`INCONSISTENT`** - The element's role has changed. `FAIL_HARD`.
167
+
168
+ The raw auditor confidence is then adjusted structurally:
169
+
170
+ - **Ancestry drift penalty** (up to −30 pts): if the parent elements have changed significantly, confidence is penalised.
171
+ - **Anchor bonus** (up to +15 pts): if the closest accessible label or row anchor text is an exact match, confidence is boosted.
172
+
173
+ An adjusted `CONSISTENT` verdict below 50% is downgraded to `SUSPICIOUS`.
174
+
175
+ #### Gate 8: Confidence Tier Decision
176
+
177
+ With all gates passed, the final confidence score determines the outcome:
178
+
179
+ - `≥ confidenceReviewThreshold` (default: **95**) → **`SAFE`** → heal is applied
180
+ - `< confidenceReviewThreshold` → **`REQUIRES_REVIEW`** → heal is quarantined
181
+
182
+ ### The Three Dispositions
183
+
184
+ Every heal exits the SafetyGuard with one of three dispositions:
185
+
186
+ | Disposition | Safety Level | Behaviour |
187
+ | ------------ | ----------------------- | -------------------------------------------------------------------- |
188
+ | **`APPLY`** | `SAFE` | Source mutation is written to disk |
189
+ | **`HOLD`** | `REQUIRES_REVIEW` | Heal is quarantined; source is untouched; `PROTECTED` event recorded |
190
+ | **`REJECT`** | `BLOCKED` / `FAIL_HARD` | Change is refused; codebase is completely untouched |
191
+
192
+ `PROTECTED` events surface prominently in the Sela Insights report, auto-expanded and annotated with the specific safety rule that blocked the change. This is a feature, not a failure - it means Sela caught a potential regression that would have silently corrupted your test suite.
193
+
194
+ ### The Internal-Selector Invariant
195
+
196
+ Playwright uses `internal:` engine selectors (e.g., `internal:role=button[name="Submit"i]`) as a private serialisation format. Sela **never** writes these into your source code - they are fragile, undocumented, and produce poor developer experience.
197
+
198
+ At every write-head, Sela intercepts internal selectors and translates them to idiomatic public Playwright methods:
199
+
200
+ - `internal:role=…` → `getByRole(...)`
201
+ - `internal:label=…` → `getByLabel(...)`
202
+
203
+ When a constant (e.g., `const SEL = "#submit"`) is being updated and `getByRole(...)` would be out of scope at the declaration site, Sela writes a clean `role=button[name="Submit"]` public locator string instead, and surfaces a `SEMANTIC_UPGRADE_SUGGESTED` advisory recommending the full method refactor as an optional next step.
204
+
205
+ ### Outbound Data Sanitization
206
+
207
+ Before any context is sent to an AI provider, Sela sanitises the payload. The following are detected and masked:
208
+
209
+ - Email addresses
210
+ - Access tokens, secrets, and credentials
211
+ - Password-like values
212
+ - Credit card numbers
213
+ - Custom project-defined sensitive patterns
214
+
215
+ Sanitisation is **enabled by default**, covers all DOM snapshots, DNA payloads, and healing context, and is fail-secure: if the sanitisation configuration fails to load, masking remains active. It can be disabled via configuration only if your project explicitly requires it.
216
+
217
+ ---
218
+
219
+ ## 3. Core Concepts
220
+
221
+ ### The DNA System - Element Fingerprints
222
+
223
+ The foundation of Sela's healing intelligence is the **DNA snapshot** - a structured JSON fingerprint of each element captured at the moment it first passes a test. Stored in `sela-snapshots/<stableId>.json`, a DNA record contains:
224
+
225
+ **Identity**
226
+
227
+ - Tag name, `id`, `role`, class list, and all HTML attributes
228
+ - `innerText` / `textContent` (trimmed)
229
+ - Bounding rect (`x`, `y`, `width`, `height`)
230
+ - Schema version (`v2`), timestamp
231
+
232
+ **Ancestry (up to 5 levels)**
233
+
234
+ - Each ancestor: tag, `id`, classes, and a structural fingerprint
235
+ - Walk stops at Shadow DOM boundaries
236
+
237
+ **Visibility State**
238
+
239
+ - Ghost conditions (G1–G6)
240
+ - Occlusion status
241
+ - Opacity value
242
+
243
+ **Contextual Anchors**
244
+
245
+ - `closestLabel`: resolved via `aria-labelledby` → `aria-label` → `label[for]` → implicit wrapper → nearest visible sibling
246
+ - `rowAnchor`: longest unique sibling cell text when the element lives in a table row
247
+ - `neighborTexts`: up to five direct-sibling texts
248
+
249
+ **Shadow DOM & Frame Awareness**
250
+
251
+ - `isInShadowDom: boolean`
252
+ - Frame traversal path for iframe-hosted elements
253
+
254
+ The `stableId` is an MD5 hash of `file:line:action[:idx]` - stable across renames but unique per action, preventing cross-call-site poisoning.
255
+
256
+ ### The Heal Pipeline
257
+
258
+ When a Playwright locator throws, Sela's `SelaEngine.heal()` runs the following sequence:
259
+
260
+ 1. Load the element's DNA snapshot (auto-migrates `v1` → `v2` on read)
261
+ 2. Extract an AI-optimised neighbourhood DOM via `DOMUtils.getNeighborhoodDom` (drills iframes and Shadow DOM, strips noise)
262
+ 3. Inject DNA context into the LLM prompt (text, role, anchor labels, row anchor, frame-path hint)
263
+ 4. Request a fix from the LLM - receives candidate selector chain + confidence + content-change assessment
264
+ 5. Live `innerText()` probe (1.5s timeout, frame-aware) - zero-trust verification baseline
265
+ 6. Atomic DNA capture of the candidate element
266
+ 7. SafetyGuard evaluation (8 gates - see §2)
267
+ 8. On `APPLY`: surgical AST source mutation via the Trace-Back Pipeline (primary) or regex fallback
268
+ 9. Capture `git diff --unified=1 HEAD` for the report
269
+ 10. Buffer `HealedEvent` / `ProtectedEvent` / `FailedEvent` for the end-of-run dashboard
270
+
271
+ ### The AST Trace-Back Pipeline
272
+
273
+ Rather than blindly overwriting a call-site string, Sela traces a failing locator back to its **source declaration** and mutates it there - preserving your code architecture.
274
+
275
+ **Example:** If `await hi.nth(3).click()` fails and `hi` was declared as `const hi = page.locator('#old-id')` in a `beforeEach`, Sela updates the declaration, not the call-site. Other tests consuming `hi` are untouched unless analysis proves the old selector is globally broken.
276
+
277
+ The pipeline has four composable stages:
278
+
279
+ | Stage | Component | Purpose |
280
+ | ----- | ----------------- | -------------------------------------------------------------------------------------------------------------- |
281
+ | 1 | `AnchorResolver` | Identifies nodes by structural signature (not line numbers), surviving concurrent edits |
282
+ | 2 | `TraceBackEngine` | Climbs the call chain to the source declaration; handles POM classes, `beforeEach` patterns, Shadow DOM chains |
283
+ | 3 | `DecisionEngine` | Chooses `MUTATE_IN_PLACE` (single consumer) vs. `FORK_AT_TEST` (multi-consumer) vs. `PROMPT_INTERACTIVE` |
284
+ | 4 | `MutationApplier` | Zero-layout-noise splice over exact character spans; type-safety gate with rollback |
285
+
286
+ The `MutationApplier` re-parses the file after mutation and runs TypeScript's `getPreEmitDiagnostics`. If the change introduces a new type error, it rolls back automatically and leaves the file untouched.
287
+
288
+ **Developer Opt-Out** - Pin any statement against Sela's pipeline with:
289
+
290
+ ```typescript
291
+ // sela-fail-fast
292
+ await page.locator("#legacy-broken").click();
293
+ ```
294
+
295
+ Sela detects this directive before making any LLM call and records a `FailedEvent` with category `"Skipped by Developer"`.
296
+
297
+ ---
298
+
299
+ ## 4. Quick Start
300
+
301
+ ### Prerequisites
302
+
303
+ - Node.js 18+
304
+ - An existing Playwright project
305
+ - An `ANTHROPIC_API_KEY` (set in your environment or `.env` file)
306
+
307
+ ### Installation
308
+
309
+ ```bash
310
+ npm install sela-core --save-dev
311
+ ```
312
+
313
+ ### Time to Value: Under 5 Minutes
314
+
315
+ **Step 1 - Initialise Sela**
316
+
317
+ Run this from your project root:
318
+
319
+ ```bash
320
+ npx sela init
321
+ ```
322
+
323
+ This command:
324
+
325
+ - Creates a `sela.config.ts` with sensible defaults
326
+ - Verifies your `ANTHROPIC_API_KEY` is accessible
327
+ - Rewrites `@playwright/test` imports to `sela-core` in your spec files
328
+
329
+ > ⚠️ Sela replaces the `@playwright/test` import surface. The full Playwright API (`test`, `expect`, `defineConfig`, `chromium`, `firefox`, `webkit`, `devices`, `selectors`) is re-exported from `sela-core` unchanged - your tests require no further modification.
330
+
331
+ **Step 2 - Add the Reporter**
332
+
333
+ In your `playwright.config.ts`:
334
+
335
+ ```typescript
336
+ import { defineConfig } from "sela-core";
337
+
338
+ export default defineConfig({
339
+ reporter: [["sela-core/reporter"]],
340
+ // ... rest of your config
341
+ });
342
+ ```
343
+
344
+ **Step 3 - Run Your Tests**
345
+
346
+ ```bash
347
+ npx playwright test
348
+ ```
6
349
 
7
- Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
350
+ When a locator failure occurs, Sela intercepts it automatically. At the end of the run, you'll see a summary table in your terminal:
8
351
 
9
- ## Add your files
352
+ ```
353
+ ┌────────────────────┬───────┐
354
+ │ 🔍 Tests Scanned │ 248 │
355
+ │ ⚠️ Errors Detected │ 3 │
356
+ │ 🛠️ Successful Heals│ 3 │
357
+ │ ⏭️ Skipped Files │ 0 │
358
+ └────────────────────┴───────┘
359
+ ```
10
360
 
11
- - [Create](https://docs.gitlab.com/user/project/repository/web_editor/#create-a-file) or [upload](https://docs.gitlab.com/user/project/repository/web_editor/#upload-a-file) files
12
- - [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
361
+ **Step 4 - Review the Report**
13
362
 
363
+ ```bash
364
+ npx sela show-report
14
365
  ```
15
- cd existing_repo
16
- git remote add origin https://gitlab.com/sela/Sela.git
17
- git branch -M main
18
- git push -uf origin main
366
+
367
+ This opens `sela-report.html` in your default browser - an interactive dashboard showing healed selectors, safety verdicts, git diffs, and ROI metrics.
368
+
369
+ ---
370
+
371
+ ## 5. CLI Reference
372
+
373
+ ### Top-Level Commands
374
+
375
+ #### `sela init`
376
+
377
+ Bootstrap Sela in your project.
378
+
379
+ ```bash
380
+ npx sela init
19
381
  ```
20
382
 
21
- ## Integrate with your tools
383
+ - Writes `sela.config.ts` to the project root
384
+ - Validates `ANTHROPIC_API_KEY`
385
+ - Migrates `@playwright/test` imports to `sela-core`
386
+
387
+ ---
388
+
389
+ #### `sela status`
22
390
 
23
- - [Set up project integrations](https://gitlab.com/sela/Sela/-/settings/integrations)
391
+ Print an ecosystem health report for your DNA index.
24
392
 
25
- ## Collaborate with your team
393
+ ```bash
394
+ npx sela status
395
+ npx sela status --json # Machine-readable JSON output
396
+ ```
26
397
 
27
- - [Invite team members and collaborators](https://docs.gitlab.com/user/project/members/)
28
- - [Create a new merge request](https://docs.gitlab.com/user/project/merge_requests/creating_merge_requests/)
29
- - [Automatically close issues from merge requests](https://docs.gitlab.com/user/project/issues/managing_issues/#closing-issues-automatically)
30
- - [Enable merge request approvals](https://docs.gitlab.com/user/project/merge_requests/approvals/)
31
- - [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
398
+ Output includes: total DNA records, healed elements, unverified heals, orphaned snapshots (source file no longer exists), heal-to-record ratio, and top healed files.
32
399
 
33
- ## Test and Deploy
400
+ ---
34
401
 
35
- Use the built-in continuous integration in GitLab.
402
+ #### `sela list`
36
403
 
37
- - [Get started with GitLab CI/CD](https://docs.gitlab.com/ci/quick_start/)
38
- - [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/user/application_security/sast/)
39
- - [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/topics/autodevops/requirements/)
40
- - [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/user/clusters/agent/)
41
- - [Set up protected environments](https://docs.gitlab.com/ci/environments/protected_environments/)
404
+ List DNA records with optional filters.
405
+
406
+ ```bash
407
+ npx sela list
408
+ npx sela list --filter "submit" # Filter by text/selector substring
409
+ npx sela list --source "checkout" # Filter by source file path
410
+ npx sela list --orphaned # Show only orphaned DNA records
411
+ npx sela list --limit 20 --json
412
+ ```
413
+
414
+ | Flag | Description |
415
+ | ----------------- | ----------------------------------------------- |
416
+ | `--filter <text>` | Substring match on selector or element text |
417
+ | `--source <path>` | Filter by source file path |
418
+ | `--orphaned` | Show only records whose source no longer exists |
419
+ | `--limit <n>` | Limit output rows |
420
+ | `--json` | Emit structured JSON to stdout |
42
421
 
43
422
  ---
44
423
 
45
- # Editing this README
424
+ #### `sela show-report`
46
425
 
47
- When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
426
+ Open the latest `sela-report.html` in your default browser, or print its absolute path.
48
427
 
49
- ## Suggestions for a good README
428
+ ```bash
429
+ npx sela show-report
430
+ ```
50
431
 
51
- Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
432
+ ---
52
433
 
53
- ## Name
434
+ #### `sela merge <glob>`
54
435
 
55
- Choose a self-explaining name for your project.
436
+ Aggregate sharded JSON payloads from parallel CI runners into a single unified report.
56
437
 
57
- ## Description
438
+ ```bash
439
+ npx sela merge ".sela/shard-outputs/*.json"
440
+ ```
58
441
 
59
- Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
442
+ Use this as the final step in a CI workflow after parallel shards complete. See [CI/CD Integration](#6-cicd-integration--sharding) for the full pattern.
60
443
 
61
- ## Badges
444
+ ---
62
445
 
63
- On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
446
+ ### `sela dna` Subcommands
64
447
 
65
- ## Visuals
448
+ #### `sela dna find`
66
449
 
67
- Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
450
+ Search your DNA index by selector, text, or source file.
68
451
 
69
- ## Installation
452
+ ```bash
453
+ npx sela dna find --selector "#submit-btn"
454
+ npx sela dna find --text "Add to Cart"
455
+ npx sela dna find --source-file "checkout.spec.ts"
456
+ npx sela dna find --json
457
+ ```
70
458
 
71
- Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
459
+ ---
72
460
 
73
- ## Usage
461
+ #### `sela dna refactor [key]`
74
462
 
75
- Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
463
+ Launch an interactive wizard to manually edit a DNA record, preview the diff, and commit the change to both the snapshot and the source file.
76
464
 
77
- ## Support
465
+ ```bash
466
+ npx sela dna refactor
467
+ npx sela dna refactor <stableId>
468
+ ```
78
469
 
79
- Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
470
+ ---
80
471
 
81
- ## Roadmap
472
+ #### `sela dna bulk-update --old --new`
82
473
 
83
- If you have ideas for releases in the future, it is a good idea to list them in the README.
474
+ Replace a selector string across all matching DNA records and their source files.
84
475
 
85
- ## Contributing
476
+ ```bash
477
+ npx sela dna bulk-update --old "#legacy-btn" --new "[data-testid='submit']"
478
+ npx sela dna bulk-update --old "#legacy-btn" --new "[data-testid='submit']" --dry-run
479
+ npx sela dna bulk-update --old "#legacy-btn" --new "[data-testid='submit']" --confirm
480
+ ```
86
481
 
87
- State if you are open to contributions and what your requirements are for accepting them.
482
+ | Flag | Description |
483
+ | ----------- | ---------------------------------------- |
484
+ | `--dry-run` | Preview changes without writing to disk |
485
+ | `--confirm` | Apply changes without interactive prompt |
88
486
 
89
- For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
487
+ ---
90
488
 
91
- You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
489
+ #### `sela dna sync-source <key>`
92
490
 
93
- ## Authors and acknowledgment
491
+ Rewrite the locator in a spec file at the exact line recorded in the DNA, to match the stored selector. Useful after manual DNA edits.
94
492
 
95
- Show your appreciation to those who have contributed to the project.
493
+ ```bash
494
+ npx sela dna sync-source <stableId>
495
+ ```
96
496
 
97
- ## License
497
+ ---
98
498
 
99
- For open source projects, say how it is licensed.
499
+ ### Global Flags
500
+
501
+ | Flag | Description |
502
+ | ----------- | --------------------------------------------------------------------------------------- |
503
+ | `--json` | Suppress spinners; redirect diagnostic output to stderr; emit structured JSON to stdout |
504
+ | `--verbose` | Enable debug-level logging (raw LLM payloads, AST transformations, DOM extractions) |
505
+
506
+ **Environment variables:**
507
+
508
+ | Variable | Effect |
509
+ | ----------------- | ---------------------------------------------------------------------------------------------------- |
510
+ | `SELA_DEBUG=1` | Equivalent to `--verbose` |
511
+ | `SELA_DRY_RUN=1` | Full heal pipeline runs but no files are written to disk; report marks cards as "Dry Run · No Write" |
512
+ | `SELA_NO_CACHE=1` | Bypass healing cache; every heal hits the LLM directly |
513
+
514
+ ---
515
+
516
+ ## 6. CI/CD Integration & Sharding
517
+
518
+ ### The Playwright Reporter
519
+
520
+ The `sela-core/reporter` integrates Sela's full heal-and-report pipeline at the Playwright reporter layer. It activates regardless of whether you are using the fixture-based `test` import.
521
+
522
+ **Reporter lifecycle:**
523
+
524
+ | Hook | What Sela does |
525
+ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
526
+ | `onBegin` | Sets `SELA_REPORTER_ACTIVE=1`; clears stale shard files from prior crashed runs |
527
+ | `onTestEnd` | For `failed`/`timedOut` results: extracts the first PNG attachment, base64-encodes it into memory, and attaches it to the corresponding `FailedEvent` |
528
+ | `onEnd` | Flushes pending screenshots → compiles report → writes history → emits HTML + JSON |
529
+
530
+ ### State Persistence in Ephemeral CI Environments
531
+
532
+ Sela maintains a 14-run rolling history window in `.sela-history.json`. In ephemeral CI environments where the filesystem resets between runs, Sela implements an **Artifact-by-last-run** strategy: the history file is fetched from the previous run's artifacts before test execution begins.
533
+
534
+ Add `.sela-history.json` to your CI artifact upload/download steps to preserve the historical trend across runs.
535
+
536
+ `.sela-history.json` and report files should be excluded from git via `.gitignore`:
537
+
538
+ ```
539
+ # .gitignore
540
+ .sela-history.json
541
+ sela-report.html
542
+ sela-report.json
543
+ .sela/
544
+ sela-snapshots/
545
+ ```
546
+
547
+ To remove any accidentally committed cache pointers:
548
+
549
+ ```bash
550
+ git rm --cached .sela-history.json
551
+ ```
552
+
553
+ ### Parallel Sharding
554
+
555
+ Sela supports Playwright's native `--shard=K/N` parallelism with no additional configuration.
556
+
557
+ **How it works:**
558
+
559
+ - Each shard runner writes an isolated payload file to `.sela/report-shards/sela-shard-<pid>-<ts>.json`. There is zero contention between runners.
560
+ - The final CI step runs `sela merge` to aggregate all shards into one unified report and one historical row.
561
+
562
+ **GitHub Actions example:**
563
+
564
+ ```yaml
565
+ # .github/workflows/test.yml
566
+ jobs:
567
+ test:
568
+ strategy:
569
+ matrix:
570
+ shard: [1, 2, 3, 4]
571
+ steps:
572
+ - run: npx playwright test --shard=${{ matrix.shard }}/4
573
+
574
+ - name: Upload shard output
575
+ uses: actions/upload-artifact@v4
576
+ with:
577
+ name: sela-shard-${{ matrix.shard }}
578
+ path: .sela/report-shards/
579
+
580
+ report:
581
+ needs: test
582
+ steps:
583
+ - name: Download all shard outputs
584
+ uses: actions/download-artifact@v4
585
+ with:
586
+ pattern: sela-shard-*
587
+ merge-multiple: true
588
+ path: .sela/report-shards/
589
+
590
+ - name: Merge Sela report
591
+ run: npx sela merge ".sela/report-shards/*.json"
592
+ ```
593
+
594
+ **Shard merge guarantees:**
595
+
596
+ - **Clock-skew immunity:** Event deduplication is keyed on `kind|stableId|normalizedPath|line|title` - timestamps are intentionally excluded, making the dedup safe across multi-region runners with clock drift.
597
+ - **Partial-failure resilience:** If a subset of shards failed (e.g., a worker crash), `sela merge` aggregates the surviving data, produces the unified report, and surfaces a prominent diagnostic warning. It does not abort the reporting pipeline.
598
+
599
+ ### CI Deduplication
600
+
601
+ When a CI job is retried (native Playwright retry or manual re-run), Sela detects the environment signature (`GITHUB_RUN_ID` or `CI_PIPELINE_ID`) and performs an **in-place overwrite** of the existing history entry for that run - preventing dataset inflation from retries.
602
+
603
+ ### Integrity Guard
604
+
605
+ `ReportMergeService` validates the structure of `.sela-history.json` on read. If a corrupt or truncated state file is detected, it throws `HISTORY_CORRUPT` and aborts - preserving the last known good state. A corrupted history file will not silently clobber valid historical data.
606
+
607
+ ---
100
608
 
101
- ## Project status
609
+ ## 7. Reporting & Insights
610
+
611
+ ### The Sela Insights Report
612
+
613
+ `sela-report.html` is a self-contained, enterprise-grade dark-mode dashboard written to disk after every run (and accessible via `sela show-report`). It has two views toggled at the top of the page:
614
+
615
+ #### The Management ROI Dashboard
616
+
617
+ Designed for engineering leads and senior management:
618
+
619
+ - **Status Donut Chart** - Live distribution of `Passed`, `Healed`, `Protected`, and `Failed` tests. Click any slice to jump to the Engineering Deep Dive, pre-filtered to that state.
620
+ - **Executive KPI Cards** - Time saved today (12 min per heal, 18 min per project win, 4 min per detected failure), cumulative bugs prevented, suite success rate, and average AI healing confidence.
621
+ - **14-Run Historical Trend Chart** - Area chart of cumulative developer hours recovered (cyan gradient) overlaid with a line tracking total self-healed selectors per run. Clean zero-heal runs appear as benchmark performance points, not gaps.
622
+ - **Recent Runs Ledger** - Tabular audit trail of historical runs with confidence ratios and saved metrics.
623
+
624
+ #### The Engineering Deep Dive
625
+
626
+ Designed for the developers who own the specs:
627
+
628
+ - **Dynamic filter chips** and a search bar supporting automated focus shortcuts
629
+ - **Healing Cards** - When expanded, each healed test shows:
630
+ - A colour-coded git diff (`--unified=1`) with exact line numbers
631
+ - An Intent Auditor Gauge: circular progress UI with safety breakdown score, ancestry penalties, anchor bonuses, and the final verdict
632
+ - AI Chain-of-Thought: collapsible logical steps (DNA recovery, layout strategies, safety bounds)
633
+ - A DNA Evidence Table: old-vs-new attribute comparison with match/mismatch indicators
634
+ - **Action Panel:** one-click copy of rollback CLI script (`npx sela dna refactor --rollback`), copy of alternative candidate locators, and a VS Code deep-link (`vscode://file/path/to/spec.ts:42`) to jump directly to the mutated line
635
+ - **Protected Event Cards** - Auto-expanded on load; annotated with the specific safety rule that blocked the change and the semantic inversion or role violation detected
636
+
637
+ ### Failure Screenshots
638
+
639
+ The reporter automatically captures the first PNG screenshot from Playwright's test attachments on failure, base64-encodes it into memory (surviving Playwright's temp-folder cleanup), and embeds it inline in the failure card in the HTML report. No additional configuration is required.
640
+
641
+ ### PR Automation
642
+
643
+ Sela can optionally open pull requests or commits for healed selectors. Configure via `sela.config.ts`:
644
+
645
+ ```typescript
646
+ prAutomation: {
647
+ enabled: true,
648
+ strategy: 'PR', // 'directCommit' | 'PR' | 'draftPR'
649
+ minAiConfidence: 90,
650
+ minAuditorConfidence: 80,
651
+ onBugDetected: true, // Open separate issue/PR for PROTECTED events
652
+ }
653
+ ```
654
+
655
+ Sela evaluates the configured strategy at runtime and **downgrades** it automatically when constraints are not met (e.g., insufficient confidence, branch policy mismatch), logging the reason.
656
+
657
+ ---
658
+
659
+ ## 8. Advanced Configuration
660
+
661
+ ### `sela.config.ts` - Full Reference
662
+
663
+ ```typescript
664
+ import { defineConfig } from "sela-core";
665
+
666
+ export default defineConfig({
667
+ // 'balanced' | 'strict' | 'loose' - preset that sets threshold defaults
668
+ policy: "balanced",
669
+
670
+ // How Sela writes heals to disk
671
+ updateStrategy: "inPlace", // 'inPlace' | 'commentOnly' | 'branch'
672
+ autoCommit: false, // Commit to current branch after healing
673
+
674
+ // SafetyGuard thresholds
675
+ thresholds: {
676
+ confidenceHardStop: 85, // Below this → BLOCKED unconditionally
677
+ confidenceReviewThreshold: 95, // Below this → REQUIRES_REVIEW
678
+ auditorConfidenceMin: 75, // Minimum adjusted auditor confidence
679
+ allowSuspicious: false, // Allow SUSPICIOUS heals through in action mode
680
+ auditorStrictness: "balanced", // 'strict' | 'balanced' | 'loose'
681
+ },
682
+
683
+ // Per-branch threshold overrides
684
+ branchOverrides: {
685
+ main: {
686
+ policy: "strict",
687
+ thresholds: { confidenceHardStop: 90, confidenceReviewThreshold: 98 },
688
+ },
689
+ },
690
+
691
+ // Write-scope allowlist (glob patterns); empty = unrestricted
692
+ allowedPaths: ["tests/**/*.spec.ts", "e2e/**/*.ts"],
693
+
694
+ // Healing budget - null = unlimited
695
+ maxHealsPerRun: 50,
696
+
697
+ // Outbound data sanitisation
698
+ sanitization: {
699
+ enabled: true,
700
+ customPatterns: [
701
+ /ACME-[A-Z0-9]{16}/g, // Custom token format
702
+ ],
703
+ },
704
+
705
+ // PR automation
706
+ prAutomation: {
707
+ enabled: false,
708
+ strategy: "PR",
709
+ minAiConfidence: 90,
710
+ minAuditorConfidence: 80,
711
+ onBugDetected: true,
712
+ },
713
+ });
714
+ ```
715
+
716
+ ### Update Strategy Modes
717
+
718
+ | Mode | Behaviour |
719
+ | ------------- | ---------------------------------------------------------------------------------------- |
720
+ | `inPlace` | Writes the healed selector directly to your spec (default) |
721
+ | `commentOnly` | Inserts `// TODO [Sela]: <new selector>` above the failing line; source is never mutated |
722
+ | `branch` | Creates a `sela/heal-<timestamp>` git branch and commits the change there |
723
+
724
+ `commentOnly` is useful when you want Sela to analyse and propose fixes in CI, but reserve the actual write for a human review step.
725
+
726
+ ### Branch Overrides
727
+
728
+ Apply tighter constraints on protected branches:
729
+
730
+ ```typescript
731
+ branchOverrides: {
732
+ main: {
733
+ policy: 'strict',
734
+ thresholds: {
735
+ confidenceHardStop: 92,
736
+ confidenceReviewThreshold: 98,
737
+ },
738
+ },
739
+ 'release/*': {
740
+ policy: 'strict',
741
+ },
742
+ },
743
+ ```
744
+
745
+ Sela detects the current branch via `git rev-parse --abbrev-ref HEAD` and merges the matching override at runtime.
746
+
747
+ ### Write Scope Protection
748
+
749
+ Restrict which files Sela is permitted to modify using glob patterns:
750
+
751
+ ```typescript
752
+ allowedPaths: [
753
+ 'tests/**/*.spec.ts',
754
+ 'e2e/pages/**/*.ts',
755
+ ],
756
+ ```
757
+
758
+ - All write-heads (`SourceUpdater`, `ASTSourceUpdater`, `InitializerUpdater`, `MutationApplier`) validate the target path against this list before writing
759
+ - Path traversal (`../`) and symlink escapes are blocked unless explicitly matched by an absolute pattern
760
+ - An empty `allowedPaths` array means unrestricted writes (backward-compatible default)
761
+
762
+ ### Heal Budget
763
+
764
+ Limit the number of AI-generated heals per run to control costs or enforce a gradual rollout:
765
+
766
+ ```typescript
767
+ maxHealsPerRun: 25,
768
+ ```
769
+
770
+ - Each AI heal consumes one budget slot
771
+ - Cache hits do **not** consume budget
772
+ - Once exhausted, additional heal attempts are skipped for that run
773
+ - Budget state is process-safe and shared across all workers
774
+
775
+ ### Dry Run Mode
776
+
777
+ Run the full healing pipeline - including LLM calls, SafetyGuard evaluation, and AST mutation - without writing anything to disk:
778
+
779
+ ```bash
780
+ SELA_DRY_RUN=1 npx playwright test
781
+ ```
782
+
783
+ The report marks healed cards as `"Dry Run · No Write"`. Use this to audit what Sela would change before enabling it in production CI.
784
+
785
+ ### The `sela-fail-fast` Directive
786
+
787
+ Exempt individual statements from healing entirely:
788
+
789
+ ```typescript
790
+ // sela-fail-fast
791
+ await page.locator("#legacy-element").click();
792
+ ```
793
+
794
+ Also accepted as `// @sela-fail-fast` or `/* sela-fail-fast */`. Sela detects this directive **before** making any LLM call - it never reaches the AI pipeline, so there is zero cost for opted-out selectors.
795
+
796
+ ---
797
+
798
+ ## 9. Error Reference
799
+
800
+ All Sela errors follow a canonical structure:
801
+
802
+ ```typescript
803
+ {
804
+ subsystem: string, // e.g. "SafetyGuard", "ASTUpdater", "Report"
805
+ code: string, // stable machine-readable code
806
+ reason: string, // human-readable explanation
807
+ context: object, // structured diagnostic context
808
+ message: string,
809
+ stack: string,
810
+ }
811
+ ```
812
+
813
+ ### SafetyGuard Codes
814
+
815
+ | Code | Trigger |
816
+ | -------------------------------- | ------------------------------------------------------- |
817
+ | `BLOCKED_LOW_CONFIDENCE` | AI confidence below `confidenceHardStop` |
818
+ | `BLOCKED_AUDITOR_SUSPICIOUS` | Intent Auditor returned `SUSPICIOUS` in assertion mode |
819
+ | `BLOCKED_ROLE_SWAP_ASSERTION` | Cross-role swap detected in assertion mode |
820
+ | `FAIL_HARD_VISIBILITY_GHOST` | Candidate element is invisible (G1–G6) |
821
+ | `FAIL_HARD_VISIBILITY_OCCLUDED` | Candidate element is covered on main/master |
822
+ | `FAIL_HARD_SEMANTIC_INVERSION` | Binary semantic opposite detected |
823
+ | `FAIL_HARD_STATUS_INVERSION` | Status role inversion (POSITIVE ↔ NEGATIVE) |
824
+ | `FAIL_HARD_AUDITOR_INCONSISTENT` | Intent Auditor returned `INCONSISTENT` |
825
+ | `FAIL_HARD_DANGEROUS_SINK` | Dangerous-sink forced audit resulted in rejection |
826
+ | `SG_HELD_FOR_REVIEW` | Heal quarantined (`REQUIRES_REVIEW`) - source untouched |
827
+ | `GENERIC_REJECTION` | Catch-all rejection |
828
+
829
+ ### CI Integrity Codes
830
+
831
+ | Code | Trigger |
832
+ | ------------------ | ------------------------------------------------------------------------------------------------------ |
833
+ | `HISTORY_CORRUPT` | `.sela-history.json` failed structural validation - pipeline aborted to preserve last-known-good state |
834
+ | `SHARD_UNREADABLE` | A shard payload failed to parse - shard is skipped; aggregate-and-flag behaviour applies |
835
+
836
+ ### Write-Scope & Budget Codes
837
+
838
+ | Code | Trigger |
839
+ | ---------------------- | ---------------------------------------------------- |
840
+ | `PATH_SCOPE_VIOLATION` | Attempted mutation outside configured `allowedPaths` |
841
+ | `HEAL_BUDGET_EXCEEDED` | `maxHealsPerRun` limit reached for this execution |
842
+
843
+ ### AST Codes
844
+
845
+ | Code | Trigger |
846
+ | -------------------------------- | ------------------------------------------------------------------ |
847
+ | `AST_HEAL_DISABLED_BY_DIRECTIVE` | `// sela-fail-fast` directive detected above the failing statement |
848
+
849
+ ### Exit Code Policy
850
+
851
+ - **Test runs** (`npx playwright test`): Playwright owns the exit code. A healed test passes → `0`. An unhealed genuine failure → `1`. Sela never converts a recoverable file-level failure into a worker crash.
852
+ - **CLI subcommands**: Fatal infrastructure failures (missing config, history corruption) → non-zero exit. Recoverable file-level failures in batch commands → `0` (execution continued).
853
+
854
+ ---
102
855
 
103
- If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
856
+ _Sela is designed to earn your trust incrementally. Start with `commentOnly` mode, review a week of proposed heals in the Insights report, then graduate to `inPlace` when you are confident. The safety pipeline is always active regardless of write mode._