Config-First Verification
When a coding agent finishes a UI task and verifies it, Verfix runs the relevant flow. If a selector doesn’t resolve, the agent has a choice:
- Fix it in Verfix configuration — the
selectorsalias map, a semantic selector, or letassistedmode heal it. ✅ - Rewrite the project’s source — e.g. add a
data-testidto a component just so the test passes. ⚠️
The second option is the easy failure mode for an agent under pressure: it rewrites production code to fit the test instead of fixing the actual gap. Verfix is built to prefer the first option — and to make the second one a typed, visible signal instead of a silent side effect.
Targeting elements without adding data-testid
Section titled “Targeting elements without adding data-testid”The primary job when writing a flow is to read the source and reuse the selector that already exists — not invent one. In priority order:
1. Reuse the element’s existing selector (primary)
Section titled “1. Reuse the element’s existing selector (primary)”Open the component and target what’s already in the code — an existing data-testid, id,
name, role, or a stable semantic CSS selector. Put it directly in the flow step, or give it a
logical name via the selectors alias map. This is deterministic and works in strict mode —
what CI runs.
{ "selectors": { "emailInput": "input[type=email]", "submitBtn": "#login-form button[type=submit]" }, "flows": [ { "id": "login", "steps": [ { "action": "click", "selector": "submitBtn" } ] } ]}The selectors alias map is for reuse and readability — the value must still be a real selector
found in the source.
2. Semantic selector
Section titled “2. Semantic selector”When there’s no stable structural selector, target by accessible role/name or visible text:
role=button[name="Sign In"], text=Sign In. Works in every mode.
3. Assisted mode — a resilience fallback, not a targeting strategy
Section titled “3. Assisted mode — a resilience fallback, not a targeting strategy”assisted mode adds self-healing: if a selector drifts and stops resolving, Verfix recovers it
at run time via the accessibility tree (aria-label / role / text), then an AI suggestion. This
is a safety net for flow stability over time — not a substitute for finding the real selector
in step 1.
Healing derives an intent hint from the selector/alias token, so descriptive names heal better: a
drifted sign-in testid or a signIn alias both map to the hint “sign in” and can re-resolve the
“Sign In” button.
4. Last resort — add data-testid to source
Section titled “4. Last resort — add data-testid to source”Only when an element genuinely can’t be targeted (e.g. an icon-only control with no accessible
name — which is also a real accessibility gap worth fixing). Add an aria-label alongside it.
The source guard (enforcement)
Section titled “The source guard (enforcement)”Instructions alone aren’t reliable, so Verfix makes source edits a typed signal in the run contract — consistent with its philosophy that reliability comes from structured contracts, not unconstrained intelligence.
How it works
Section titled “How it works”verfix run snapshots a git baseline at the start of each verify cycle:
- The first run of a cycle baselines the working tree — your feature work is not flagged.
- Later runs report project files changed since the baseline — i.e. edits made inside the edit → verify → fix loop, where the anti-pattern lives.
- A passing run ends the cycle and clears the baseline. A new git commit also starts a fresh cycle.
- Outside a git repo, the guard disables itself and never blocks a run.
The JSON output gains a source_changes field:
{ "passed": true, "source_changes": { "status": "ok", "baseline_captured": false, "files": [{ "path": "src/LoginForm.tsx", "classification": "project" }], "project_count": 1, "config_count": 0 }}.verfix/**, verfix.config.*, and agent instruction files (AGENTS.md, CLAUDE.md, GEMINI.md,
CODEX.md, .cursorrules, .cursor/**, .github/copilot-instructions.md,
.github/instructions/**, .clinerules/**, .agents/**) are classified as config; everything
else is project.
sourceCodePolicy
Section titled “sourceCodePolicy”Set the policy in verfix.config.json, or override per run with --source-policy:
| Policy | Behavior |
|---|---|
warn (default) | Run still passes, but reports changed project files and adds a source_edit_warning finding. Doesn’t block legitimate app-bug fixes. |
block | If project source changed during the loop, the run fails with a source_edit_blocked failure until reverted. Best for CI. |
off | No source-change detection. |
{ "sourceCodePolicy": "warn" }verfix run --flow login --source-policy block --output jsonverfix run --flow login --reset-baseline --output json # start a fresh cycleWhen you see a source_edit_blocked / source_edit_warning finding: if the edit wasn’t a genuine
bug fix, revert it and target the element via the selectors alias map or assisted mode instead.
See also
Section titled “See also”- Execution Modes — strict vs. assisted vs. exploratory
- Agent Integration — how agents drive Verfix, the output contract
- Config Reference — the
selectorsmap andsourceCodePolicyfield