mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
7.6 KiB
7.6 KiB
Agent Device Domain Context
Terms
- Provider-backed integration scenario: device-free integration test that runs the real daemon request path and replaces only external device or host tool execution.
- Provider: request-scoped adapter interface for external device, runner, or host tool execution.
- Provider transcript: exact record of provider calls used when a test must verify platform command translation.
- Scenario transcript: command-level integration flow that describes user-visible behavior through daemon commands.
- In-process provider scenario harness: integration runner that invokes the daemon request handler directly without opening an HTTP listener.
- HTTP contract test: narrow test that verifies JSON-RPC transport, auth, and response finalization over the daemon HTTP boundary.
- Daemon RPC protocol version: integer advertised by daemon/proxy
/healthand checked by remote clients before HTTP JSON-RPC; bump only for breaking transport/request/response compatibility across the remote daemon boundary. - Interactor: semantic interface between command dispatch and platform behavior.
- Platform module: platform-specific implementation behind the Interactor.
- Target: selected automation destination, such as mobile, tv, or desktop.
- Modality: broad supported device family, such as mobile, tv, or desktop.
- Session: daemon-owned state for a selected target and opened app or surface.
- Command surface: catalog of public command identity, interface exposure, adapter policy, and shared command metadata across CLI, Node.js, MCP, and batch entrypoints.
- Daemon command registry: daemon-side source of truth for command route ownership and request-policy traits, including admission exemptions, session locking, selector validation, replay-scoped actions, recording invalidation, Android dialog guards, and request provider device resolution.
- Runner command traits: per-command-type classification for iOS/macOS runner lifecycle behavior, distinct from the public command surface and daemon command registry. The Swift runner traits classify interaction, read-only, and runner-lifecycle axes for XCTest execution; Swift resolves the alert command as read-only only for its
getaction. The TypeScript runner command traits classify daemon-side runner send/recovery policy such as read-only retry routing, readiness probes, and recent-healthy-mutation preflight skips; the TypeScript table is command-type keyed and currently classifies alert as read-only for daemon retry policy. Each side keeps one source of truth keyed by runner command type. - Coordinate-first resolved element activation: iOS/macOS runner interaction pattern where a selector or text query resolves the semantic
XCUIElement, then activation uses the element's resolved center coordinate when a frame is available. This keeps target selection semantic while avoidingXCUIElement.tap()post-action element re-resolution after normal navigation. tvOS remains focus/remote-driven. - Snapshot capture plan: per-strategy ordered chain of iOS snapshot capture backends (recursive tree, query sweep, private AX) run by one plan runner under a shared wall-clock budget; recovery ordering is declared data, never a per-call-site branch.
- Snapshot quality verdict: structured outcome (state, backend, reason code, effective depth, collapsed leaves) computed once by the plan runner and shipped with every planned snapshot payload; the daemon and CLI render it instead of re-deriving degradation from node shapes.
- AX-unavailable target invalidation: iOS/macOS runner behavior where a root accessibility snapshot failure such as
kAXErrorIllegalArgumentmarks the cachedXCUIApplicationtarget handle suspect. The runner fails closed for degraded interactive snapshots, clears the cached target, and lets the next command reacquire the app through normal activation.
Selector Capture Reliability Contract
Selector capture is allowed to optimize transport, helper reuse, and polling, but it must preserve the observable freshness and failure semantics below before any runtime refactor.
- Direct iOS selector queries are a narrow fast path only: iOS, simple one-term
id/label/text/valueselectors, and never whilepostGestureStabilizationis pending. A direct miss may fall back to the snapshot selector path, but ambiguous matches and runner errors must surface instead of silently falling back.get textuses direct native selectors only for simpleidselectors because label/text/value reads need snapshot disambiguation. - Regular selector reads remain capture-backed.
@refreads resolve against stored session snapshots; selectorget/is/find/waitcapture through the backend.findandwaitpolling must bypass the 750 ms snapshot cache. The cache is also bypassed while Android freshness recovery or post-gesture stabilization is active. - Sparse snapshot quality verdicts are observable failures. Sparse captures must not replace
session.snapshot, and selector routes should report the sparse verdict instead of treating a root-only or sparse tree as an empty UI. - iOS sparse and AX failures are not proof of empty UI. Regular visible snapshots can recover
through the capture plan; raw and strict paths preserve failure.
runnerFatalinvalidates the cached target and must never refresh healthy mutation recency. - Android helper reuse must not become snapshot result caching. Freshness is short lived, marked only after navigation-sensitive actions, compared against broad route-safe baselines, and not learned from scoped, depth-limited, interactive, or ref-refresh snapshots.
- Pending interaction outcome retry runs before post-gesture stabilization. Android freshness then composes when needed. Stabilization applies after swipe, scroll, gesture, or an explicit flag, and disables direct iOS selector shortcuts while pending.
setSessionSnapshotis the centralized session snapshot mutation path. Sparse captures do not write back, and empty@ref-scoped snapshot output must not replace the stored session snapshot.- Maestro target matching remains snapshot-based, fresh, and policy-rich. Native selector simplification must not erase Maestro regex/string selector behavior, visibility filtering, ranking, fuzzy fallback, visible-context preference, Android duplicate handling, tab-strip inference, or assertion/wait semantics.
Evidence: ADR 0002,
ADR 0004,
ADR 0005,
Maestro compatibility debt map,
find.test.ts,
snapshot-handler.test.ts,
snapshot-scoped-refs.test.ts,
runtime-targets.test.ts, and
android-test-suite.test.ts.
Testing Principles
- Provider-backed integration scenarios should exercise the public daemon path whenever practical.
- Prefer the in-process provider scenario harness for broad scenarios; keep HTTP contract tests narrow and transport-specific.
- Provider seams sit below platform modules so integration tests still cover platform command translation.
- Provider transcripts are for exact external command contracts.
- Scenario transcripts are for broad, user-rooted workflows that should replace mocked handler unit tests.
- Unit tests stay for pure logic, parser matrices, selector matching, capabilities, and important edge cases.