Skip to content

[BE-0280] feat(conformance): actuate text-editing and tap_point in the driver contract#1204

Merged
hirosassa merged 6 commits into
mainfrom
claude/be-0280-conformance-unactuated-verbs
Jul 19, 2026
Merged

[BE-0280] feat(conformance): actuate text-editing and tap_point in the driver contract#1204
hirosassa merged 6 commits into
mainfrom
claude/be-0280-conformance-unactuated-verbs

Conversation

@hirosassa

Copy link
Copy Markdown
Collaborator

Summary

Extends the driver conformance contract (BE-0114) to the Driver operations no lane actuated under the contract before: the text-editing family (select_all / copy_selection / delete_text) and tap_point. Previously each backend's command construction was unit-tested with a mocked subprocess, but no lane exercised the round-trip from a step to an observed field change — a capability the tool advertised but no lane observed. This closes that gap with one spec that runs on every backend. Implements BE-0280.

What changed

  • New capability Capability.TEXT_SELECTION (bajutsu/drivers/base.py) for select-all + clipboard copy on the focused field. XCUITest / adb / Playwright / fake declare it; idb — coordinate-only, no select-all handle — does not and raises UnsupportedAction, the same actuate-or-raise promise as MULTI_TOUCH.
  • Preflight gate (bajutsu/capability_preflight.py): select / copy steps require TEXT_SELECTION, so an idb scenario using them fails up front (like selectOption) instead of late. delete / clear stay ungated — every backend backs delete_text.
  • Three contract bodies in tests/driver_conformance.py: text-selection actuate-vs-raise, delete_text reduces the field length, and tap_point focuses the field like a semantic tap.
  • An always-present editable field on every conformance screen — iOS ConformanceView, Compose ConformanceScreen, web _render, and the now-reactive FakeConformanceHarness on the gate. Its known, queryable frame doubles as the coordinate tap's target, so no separate known-frame element is needed. The typed text surfaces as the element value on every backend (iOS AXValue, web input.value, adb via a content-desc mirror since adb maps textlabel).
  • Docs: docs/drivers.md (capability table + preflight), docs/architecture.md (conformance invariants), both with their docs/ja/ mirrors.

Prime-directive compliance

  • AI is never the judge. No LLM anywhere near this — the contract is deterministic pytest, judged by make check and the E2E workflows.
  • Determinism first. No fixed sleep; the round-trip is observed via query() deltas. A backend that declares TEXT_SELECTION must actuate; one that does not must raise loudly (no silent no-op).
  • App-agnostic. The change is in the driver contract and the shared conformance screens; no per-app knobs.

Verification

  • make check — green (FakeDriver conformance lane, preflight, all unit tests; 92.4% coverage).
  • Web lane (-m web) — green against real headless Chromium locally (the 3 new bodies included).
  • idb / XCUITest / adb lanes — run in ios-e2e.yml / android-e2e.yml on this PR; the new field surfaces its value on each so the round-trip is observed on-device.

Roadmap

Flips BE-0280 to Implemented in both language files and reindexes.

🤖 Generated with Claude Code

…ontract

Extend the driver conformance contract (BE-0114) to the Driver operations no
lane actuated under it: select_all / copy_selection, the delete_text round-trip,
and tap_point (BE-0280).

- Add a `Capability.TEXT_SELECTION` token for select-all + clipboard copy on the
  focused field. XCUITest / adb / Playwright / fake declare it; idb, coordinate-
  only with no select-all handle, does not and raises `UnsupportedAction`.
- Gate `select` / `copy` steps on it in the preflight (`capability_preflight.py`),
  exactly like `selectOption`, so an idb scenario fails up front rather than late.
  `delete` / `clear` stay ungated — every backend backs `delete_text`.
- Add three contract bodies to `tests/driver_conformance.py`: text-selection
  actuate-vs-raise, delete-reduces-length, and tap_point focusing the field like a
  semantic tap. Each conformance screen (iOS `ConformanceView`, Compose
  `ConformanceScreen`, web `_render`, and the reactive `FakeConformanceHarness` on
  the gate) grows one always-present editable field, whose known frame doubles as
  the coordinate tap's target.
- Update docs/drivers.md, docs/architecture.md (both languages) and flip the
  roadmap item to Implemented.

Verified: `make check` green (FakeDriver lane) and the web lane green against
real Chromium; idb / XCUITest / adb lanes verify in the E2E workflows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added topic:dogfood Dogfood fixtures (demo apps) (roadmap topic) topic:platform Platform expansion (Android / Web / Flutter) (roadmap topic) labels Jul 19, 2026
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hirosassa and others added 2 commits July 19, 2026 21:33
fb-idb's client.text() maps each character through KEY_MAP, which has no
entry for the backspace control character and raises "No keycode found for".
Route delete_text through client.key_sequence with the Delete/Backspace HID
keycode instead, the hardware backspace the field honors natively. Splits the
shared companion helper so typing keeps client.text and deleting uses key
events, and pins the seam with a Fake-lane test (skipped without the idb extra).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The conformance TextField carried an explicit .accessibilityValue(fieldText)
bound to its per-keystroke state, which made SwiftUI re-create the field's
accessibility element on every change, so an XCUITest handle resolved just
before a keystroke went stale under the element. A SwiftUI TextField already
surfaces its bound text as its accessibility value natively (as SearchView's
field does), so drop the explicit modifier: the round-trip value stays
observable while the node identity stabilizes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread tests/driver_conformance.py Outdated
A text-editing conformance test leaves iOS transient UI up — the keyboard,
and after select-all/copy the system edit menu (a PopoverDismissRegion
backdrop). That floats above ConformanceView, so re-rendering the seeded
content on a reseed does not clear it; it obscured the next screen's readiness
marker, and the harness's readiness probe saw only PopoverDismissRegion — the
field/marker gone. It also churned the XCUITest field handle to stale.

Resign the field and end editing app-wide when the screen is reseeded
(identifiers change). Deterministic (no fixed sleep), app-side, so the
backend-agnostic contract stays free of any iOS-specific teardown.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reuse the shared geometry helper (BE-0251) the backends use rather than a
second copy of the (x + w/2, y + h/2) arithmetic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@hirosassa
hirosassa marked this pull request as ready for review July 19, 2026 20:12
@hirosassa
hirosassa merged commit 8b69c5b into main Jul 19, 2026
39 checks passed
@hirosassa
hirosassa deleted the claude/be-0280-conformance-unactuated-verbs branch July 19, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:dogfood Dogfood fixtures (demo apps) (roadmap topic) topic:platform Platform expansion (Android / Web / Flutter) (roadmap topic)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant