Files
skill-template/tools/ui_inspector/locators/validator.py
chendelian 633ecff4e2 chore: archive tools/ui_inspector snapshot before migration removal.
Keep the last in-template copy on main so history can restore it; product continues in jiangchang-ui-recorder.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 11:19:14 +08:00

51 lines
1.6 KiB
Python

"""Locator uniqueness validation against snapshot / live tree rows."""
from __future__ import annotations
from typing import Any, Optional
from models.locator import LocatorCandidate
from .base import count_matches
def validate_locator_against_rows(
candidate: LocatorCandidate,
rows: list[dict[str, Any]],
*,
level: str = "snapshot_only",
expected_count: int = 1,
) -> LocatorCandidate:
"""
Validate structured locator properties against a row list.
Levels supported in this phase: snapshot_only | live_tree
"""
actual = count_matches(
rows,
properties=candidate.properties,
scope=candidate.scope,
)
candidate.mark_counts(actual, expected=expected_count)
candidate.validation = level
if not candidate.unique:
candidate.reasons = list(candidate.reasons or [])
if "ambiguous_match_count" not in candidate.reasons:
candidate.reasons.append("ambiguous_match_count")
candidate.production_eligible = False
if candidate.uses_coordinates:
candidate.production_eligible = False
if "coordinates_never_primary" not in (candidate.reasons or []):
candidate.reasons = list(candidate.reasons or []) + ["coordinates_never_primary"]
return candidate
def choose_production_primary(
candidates: list[LocatorCandidate],
) -> Optional[LocatorCandidate]:
"""Return first production-eligible unique non-coordinate locator, else None."""
for c in candidates:
if c.production_eligible and c.unique and not c.uses_coordinates:
return c
return None