Files
callstack__agent-device/CHANGELOG.md
Michał Pierzchała e70fac7b44 fix(ios): deny viewport during capability admission on Apple targets (#1507)
The capability matrix admitted `viewport` on every Apple simulator and
device while no Apple interactor implements `setViewport`, so the command
was routed to the device and only rejected inside dispatch with the
backend-shaped "viewport is not supported by this backend". Nothing can
serve it there: Apple screen geometry is fixed by the selected device type
and neither simctl nor XCTest exposes a resize primitive, so viewport is a
web-surface contract (its CLI summary and docs already say so).

Deny it in the descriptor's capability facet, matching the adjacent Android
denial, and give the Apple family an unsupported hint that names the surface
that does support it. Admission now fails before the request reaches the
device: "viewport is not supported on this device" with supportedOn: web.

The iOS simulator coverage manifest's known-gap row becomes a
capability-denial row owned by the static coverage test, which retires the
whole known-gap level and the `full:known-gaps` live scenario that existed
only to pin this failure.

Closes #1407
2026-07-30 20:22:17 +02:00

6.0 KiB

Changelog

Unreleased

  • viewport is now rejected during capability admission on Apple targets instead of reaching the device and failing inside dispatch. No Apple backend can resize a screen — simulator and device geometry is fixed by the selected device type — so viewport on iOS/iPadOS/tvOS/macOS now fails with UNSUPPORTED_OPERATION, viewport is not supported on this device, and a hint pointing at --platform web and at picking a different simulator. capabilities no longer advertises viewport on Apple targets. Web viewport resizing (agent-device viewport 1280 900 --platform web) is unchanged, and Android was already denied.
  • --save-script is now accepted only by the commands that declare it — open, close, and replay. A hand-built daemon request (or a batch step) that set saveScript on any other command, such as record or trace, used to arm script publication and could write a .ad artifact; it is now rejected with INVALID_ARGS before the request reaches admission, the device, or any handler. CLI, Node, and MCP usage of --save-script on its documented commands is unchanged.
  • diff screenshot no longer runs the retired best-effort OCR and non-text analyzers. Their optional ocr and nonTextDeltas fields remain in the result type for source compatibility but are no longer emitted; use the baseline/current images and diff artifact with vision for qualitative interpretation.
  • Breaking: removed the deprecated --session-locked and --session-lock-conflicts flags. Use --session-lock reject|strip instead; passing either old flag now fails with Unknown flag: ... Use --session-lock reject|strip instead.
  • Breaking: removed the replay export --format flag. replay export always writes Maestro YAML.
  • Breaking: removed the unused LeaseAllocatePayload, LeaseHeartbeatPayload, and LeaseReleasePayload type exports from agent-device/contracts. Lease request metadata is fully described by DaemonRequestMeta.
  • Maestro compat: assertVisible and assertNotVisible now accept childOf for ancestor scoping, matching tapOn (#1294).
  • Breaking: removed deprecated gesture duration and rotate velocity inputs (#1218).
    • swipe x1 y1 x2 y2 no longer accepts a trailing durationMs positional; use gesture pan x1 y1 (x2-x1) (y2-y1) durationMs for deliberate timed drags.
    • Maestro swipe operations with a duration continue to normalize to gesture pan with the endpoint-hold execution profile, preserving the Maestro-compatible fast-swipe-then-hold behavior on iOS.
    • gesture fling direction x y no longer accepts a trailing durationMs positional; use gesture pan for timed movement.
    • gesture swipe preset no longer accepts a trailing durationMs positional; use gesture pan for timed movement.
    • gesture rotate degrees [x] [y] no longer accepts a trailing velocity positional; rotation pacing is derived from degrees.
    • MCP/Node schemas no longer advertise velocity or durationMs on swipe/fling/gesture swipe; durationMs remains on gesture pan and gesture transform.
    • A .ad script that still carries a removed positional now fails when the script is parsed, before the replay executes any device action, naming the line and its rewrite (for example swipe accepts 4 arguments: x1 y1 x2 y2 (line 6). The trailing durationMs positional was removed: use "gesture pan 197 650 0 -350 300" ...). Previously the script ran up to that step and then failed as a replay divergence.
    • Published the gesture migration guide covering CLI, Node.js, MCP, and saved .ad recordings, plus the deprecation policy the next such removal follows (#1216).
    • replay export now writes an explicit duration: 100 for swipe — the canonical fling duration — instead of omitting it and letting Maestro apply its own 400ms default. Maestro flows replayed by agent-device are unaffected; a timed Maestro swipe still normalizes to gesture pan with the endpoint-hold profile.
  • Breaking: the deprecated rotate CLI command alias has been removed. Use orientation instead; invoking rotate now fails with rotate was renamed to orientation; for the two-finger gesture use: gesture rotate.
  • Breaking (ADR 0014, session ref-frame lifetime): a mutation through an @ref now expires the session's ref frame, so a later ref mutation without a fresh observation fails closed with a typed details.reason (ref_frame_expired, ref_generation_mismatch, plain_ref_requires_complete_frame, or ref_not_issued) instead of acting on a possibly-navigated screen. A ref-oriented sequence that performs several mutations must re-snapshot between them, consume an honestly issued --settle ref in pinned @eN~s<gen> form, or use selectors. Enforcement applies on every platform, not just iOS. Legacy hand-written .ad scripts that reuse several bare refs from one snapshot must capture between mutations or use selectors.
  • Ref reads resolve against the authorized ref frame's source tree, so an internal read-only capture (including Android freshness) can no longer retarget an admitted @ref by positional coincidence. Read-only ref consumers keep the structured staleness warning while the frame retains the ref's evidence.

0.15.0

  • Breaking: apps discovery and public app-list helpers now default to user-installed apps. Use --all or filter: 'all' to include system/OEM apps.
  • Breaking: removed the agent-device/android-apps public subpath. Use the Android app helpers from agent-device/android-adb.
  • Breaking: removed the agent-device/daemon public subpath. Use agent-device/contracts for daemon request/response types.
  • Breaking: removed public local ADB bypass/selection helpers such as spawnAndroidAdbBySerial and resolveAndroidAdbProvider; use createLocalAndroidAdbProvider(device) or pass providers directly to the helpers from agent-device/android-adb.
  • Added Android ADB provider helpers for exec, stream, clipboard, keyboard, app lifecycle, logcat, and port reverse workflows.