# ADR-0001: Accessibility Tree for Element Targeting

## Status

Accepted

## Context

Browser automation tools typically use CSS selectors or XPath to find elements:

```python
# Playwright approach
page.click('button[data-testid="submit"]')
page.fill('#email-input', 'user@example.com')

# Selenium approach
driver.find_element(By.CSS_SELECTOR, '.submit-btn')
```

**Problems with CSS selectors:**

1. **Brittle** — Frontend changes break selectors (`#submit-btn` → `.submit-btn`)
2. **Framework-specific** — React/Vue/Angular generate different class names
3. **Dynamic IDs** — `#react-root-42` changes between sessions
4. **No semantic meaning** — `.btn.btn-primary` tells you nothing about purpose

## Decision

We use the **accessibility tree** for element targeting, similar to agent-browser:

```python
# Browser Hybrid approach
tree = browser.accessibility_tree()
print(tree.to_tree_str())
# - RootWebArea "GitHub" [ref=1]
#   - link "Sign in" [ref=42]
#   - textbox "Email" [ref=43]
#   - button "Submit" [ref=44]

browser.click("42")        # By accessibility ref
browser.click_by_text("Sign in")  # By visible text
browser.type_by_name("Email", "user@example.com")  # By label
```

**Benefits:**

1. **Semantic** — "button 'Submit'" is meaningful, `#btn-42` is not
2. **Stable** — Accessibility roles don't change with CSS
3. **Framework-agnostic** — Works the same for React/Vue/Angular
4. **Human-readable** — Tree output makes debugging easy
5. **Closest to user intent** — What a user would click/type

## Consequences

### Positive

- **More stable tests** — Less brittle than CSS selectors
- **Easier debugging** — Print tree, see what's there
- **Semantic assertions** — "Find login button" vs "Find #btn-login"
- **Matches user perspective** — Users click buttons, not CSS selectors

### Negative

- **Requires Chrome** — Other browsers not yet supported
- **Extra CDP call** — Need to fetch accessibility tree first
- **Not all elements accessible** — Some custom components need workarounds
- **Ref IDs change** — Must re-fetch tree after navigation

### Mitigations

- **click_by_text()** — Use visible text when ref is unstable
- **type_by_name()** — Use label/name for form fields
- **Cache tree** — Accessibility tree stable during single page state

## Examples

### Before (Playwright)

```python
# Breaks when frontend changes class names
page.click('button[data-testid="submit-button"]')
page.fill('input[name="email"]', 'user@example.com')
```

### After (Browser Hybrid)

```python
# Stable across frontend changes
browser.click_by_text("Submit")
browser.type_by_name("Email", "user@example.com")

# Or get refs for complex interactions
tree = browser.accessibility_tree()
submit = tree.find_by_role("button", name="Submit")[0]
browser.click(submit.ref)
```

## References

- [Chrome DevTools Protocol - Accessibility domain](https://chromedevtools.github.io/devtools-protocol/tot/Accessibility/)
- [agent-browser accessibility approach](https://github.com/nickyouttail/agent-browser)
- [Web Accessibility Initiative](https://www.w3.org/WAI/)