Failure classes¶
Every failed keyword is classified into exactly one failure class. Deterministic detectors run first (no LLM); a single-shot triage agent classifies only when no detector matches. Each class has its own healing strategy and opt-in flags.
| Class | Detected when | Healing action | LLM? | Opt-in |
|---|---|---|---|---|
timing |
document.readyState != complete |
wait for ready, rerun | no | — |
overlay |
an open <dialog>/banner intercepts, target still present |
dismiss a verified control, rerun | no¹ | — |
viewport |
element exists but outside the viewport (web) / absent from the current screen (mobile) | scroll / bounded swipe into view, rerun | no | — |
assertion-drift |
RF assertion message Text 'x' should be 'y' |
verify drift, rerun with corrected expectation | yes (vision optional) | HEAL_HEAL_ASSERTIONS |
form-state |
required-but-empty / aria-invalid fields on a blocked submit |
diagnose the fields; optionally fill | DOM + optional vision | HEAL_FORM_FILL (fill) |
locator-drift |
locator matches 0 elements (or is ambiguous) | propose → verify → rerun (tiered) | yes | — |
unknown |
nothing else matches | root-cause analysis only | triage only | — |
¹ The dismiss control is chosen by deterministic heuristics; an LLM is used only to pick among already-verified candidate controls.
Detection order¶
The order is deliberate — a loading page explains everything, a blocking dialog beats out-of-viewport (both need the element present), and the mobile viewport branch runs before locator-drift and falls through to it when swiping finds nothing.
flowchart TD
F[keyword fails] --> T{page loading?}
T -->|yes| TIMING[timing: wait + rerun]
T -->|no| O{open dialog blocks?}
O -->|yes| OVERLAY[overlay: dismiss + rerun]
O -->|no| V{element exists,<br/>out of viewport?}
V -->|yes| VIEWPORT[viewport: scroll/swipe + rerun]
V -->|no| A{assertion message?}
A -->|yes| ASSERT[assertion-drift]
A -->|no| FORM{required fields<br/>unfilled?}
FORM -->|yes| FORMSTATE[form-state]
FORM -->|no| L{locator matches<br/>0 / many?}
L -->|yes| LOC[locator-drift]
L -->|no| TRIAGE[triage agent → class or unknown]
Always-on output¶
Healed, unhealed, or suppressed — every transaction produces a typed root-cause record and a report event. Healing is never the only product: the enriched error for an unhealable failure is half the value.
See Failure taxonomy and triage for the
reasoning behind this design, and Tiered locator healing
for how locator-drift is repaired.